easy-sql 0.101.1

Macro-first SQL toolkit with compile-time checked queries, optional migrations on top of sqlx.
Documentation
//! Prototype output implementation for query! macro

use anyhow::Context;
use easy_macros::always_context;
use futures::StreamExt;

use crate::{
    Connection, Driver, Output, Table,
    macro_support::never_any,
    traits::{DriverArguments, InternalDriver},
};

use super::TestDriver;
#[derive(Debug, Table)]
#[sql(no_version)]
#[sql(table_name = "example_table_query_lazy")]
struct ExampleTable {
    #[sql(primary_key)]
    id: i64,
    field0: String,
    field1: String,
    field2: i32,
    field3: i64,
    field4: i16,
}
#[allow(dead_code)]
#[derive(Debug, Output)]
#[sql(table = ExampleTable)]
struct ExampleOutput {
    field1: String,
    field2: i32,
    field3: i64,
}
#[always_context]
#[no_context]
#[allow(dead_code)]
async fn _test_select() -> anyhow::Result<Vec<ExampleOutput>> {
    let mut fake_conn = never_any::<Connection<TestDriver>>();

    let random_id = 42;

    // query_lazy!(SELECT ExampleOutput FROM ExampleTable WHERE id = {random_id} AND field2 > 17);

    let mut whatever_vec = Vec::new();

    // query! macro output
    let mut lazy_handler = {
        //Place Security checks here
        let _ = || {
            fn to_convert_single_impl<
                Y: crate::markers::ToConvertSingle<TestDriver>,
                T: crate::Output<ExampleTable, TestDriver, DataToConvert = Y>,
            >(
                _el: T,
            ) {
            }
            to_convert_single_impl(never_any::<ExampleOutput>());
        };
        // Imports
        use anyhow::Context;
        use sqlx::Arguments;
        let mut args = DriverArguments::<TestDriver>::default();
        let mut query = "SELECT ".to_string();
        let current_arg_n = 0;
        let mut _easy_sql_d = TestDriver::identifier_delimiter();
        // Build query
        <ExampleOutput as Output<ExampleTable, TestDriver>>::select(&mut query);
        query.push_str(" FROM ");
        query.push_str(<ExampleTable as Table<TestDriver>>::table_name());
        query.push_str(&format!(
            " WHERE {_easy_sql_d}id{_easy_sql_d} = {} AND {_easy_sql_d}field2{_easy_sql_d} > {}",
            TestDriver::parameter_placeholder(current_arg_n),
            TestDriver::parameter_placeholder(current_arg_n + 1)
        ));
        args.add(&random_id).map_err(anyhow::Error::from_boxed)?;

        let builder = sqlx::QueryBuilder::with_arguments(query, args);

        struct LazyQueryResult<'_easy_sql_a> {
            builder: sqlx::QueryBuilder<'_easy_sql_a, InternalDriver<TestDriver>>,
        }

        impl<'_easy_sql_q> LazyQueryResult<'_easy_sql_q> {
            fn fetch<'_easy_sql_e, E>(
                &'_easy_sql_e mut self,
                conn: E,
            ) -> impl futures::Stream<Item = anyhow::Result<ExampleOutput>> + '_easy_sql_e
            where
                E: sqlx::Executor<
                        '_easy_sql_e,
                        Database = crate::traits::InternalDriver<TestDriver>,
                    >,
                '_easy_sql_q: '_easy_sql_e,
            {
                self.builder.build().fetch(conn).map(|r| {
                    match r {
                        Ok(r) => {
                            let converted =
                                <ExampleOutput as Output<ExampleTable, TestDriver>>::convert(r)?;

                            Ok(converted)
                        }
                        Err(err) => Err(anyhow::Error::from(err)),
                    }
                    .with_context(|| "Generated by macro")
                })
            }
        }

        LazyQueryResult { builder }
    };

    let mut rows = lazy_handler.fetch(&mut *fake_conn);

    {
        while let Some(item) = rows.next().await {
            whatever_vec.push(item.context("whatever")?);
        }
    }

    Ok(whatever_vec)
}