qraft 0.1.2

Typed Rust query builder with CTE and soft-delete support.
Documentation
extern crate self as qraft;

#[cfg(feature = "chrono")]
pub use chrono;
pub use qraft_core::expression::CompareUntyped;
pub use qraft_core::query::select;
use qraft_core::quex as quex_core;
pub use qraft_core::quex::{
    Column as QuexColumn, ColumnIndex as QuexColumnIndex, ColumnType as QuexColumnType,
    ConnectOptions, Connection, Decode, Decoder, Driver, Encode, EncodeTarget, Encoder, Error,
    ExecResult, Executor, FromColumnRef, FromRowRef, Hooks, IntoConnectOptions,
    MysqlConnectOptions, ParamRef, ParamSource, Params, Pool, PoolBuilder, PoolStatement,
    PoolTransaction, PooledConnection, PooledStatement, PooledTransaction, PostgresConnectOptions,
    Prepare, PreparedStatement, Result, Row, RowRef, RowStream, Rows, SqliteConnectOptions,
    Statement, Transaction, Value, prepare, query,
};
pub use qraft_core::{
    aggregate, alias, builder, cte, delete_from, expression, insert_into, query, raw, relation,
    update, with, with_recursive, AttachInput, BigInt, Blob, Bool, Compatible, Date,
    DefaultMeta, DefaultQueryPolicy, DraftField, Draftable, FindsByKey, Float, FromPivotRow,
    FromPrefixedRow, FromRow, Int, ModelKey, ModelQueryPolicy, MorphName, MySql, NotNull, Null,
    Nullable, Pivot, Postgres, Qrafting, Query, QueryOf, QueryVisibility, RelationForeignKey,
    RelationForeignKeyRef, RelationMorphType, RelationQuery, SaveDraft, SaveResult, Sqlite,
    SyncResult, SyncWithoutDetachingResult, Text, Time, Timestamp, ToggleResult, UBigInt, UInt,
    Untyped,
};
#[cfg(feature = "hash")]
pub use qraft_core::Hashed;

pub mod quex {
    use crate::{Encode, ExecResult, Executor, FromRow, Result, RowStream, Rows};
    use crate::quex_core;
    use std::marker::PhantomData;

    pub type Error = crate::Error;
    pub type Pool = crate::Pool;
    pub type Row = crate::Row;
    pub type ResultRow<'a> = Rows<'a>;

    pub struct Query<'q> {
        inner: quex_core::Query<'q>,
    }

    impl<'q> Query<'q> {
        pub fn bind<T>(mut self, value: T) -> Self
        where
            T: Encode,
        {
            self.inner = self.inner.bind(value);
            self
        }

        pub async fn execute(self, exec: impl Executor) -> Result<ExecResult> {
            self.inner.execute(exec).await
        }

        pub async fn fetch_one(self, exec: impl Executor) -> Result<Row> {
            let mut exec = exec;
            let mut rows = self.inner.fetch(&mut exec).await?;
            rows.next()
                .await?
                .map(|row| row.to_owned())
                .transpose()?
                .ok_or_else(|| Error::Unsupported("expected at least one row, got zero".into()))
        }
    }

    pub fn query(sql: &str) -> Query<'_> {
        Query {
            inner: quex_core::query(sql),
        }
    }

    pub struct QueryAs<'q, T> {
        inner: quex_core::Query<'q>,
        marker: PhantomData<T>,
    }

    impl<'q, T> QueryAs<'q, T> {
        pub fn bind<U>(mut self, value: U) -> Self
        where
            U: Encode,
        {
            self.inner = self.inner.bind(value);
            self
        }

        pub async fn fetch_one(self, exec: impl Executor) -> Result<T>
        where
            T: FromRow,
        {
            self.inner.one(exec).await
        }
    }

    pub fn query_as<T>(sql: &str) -> QueryAs<'_, T> {
        QueryAs {
            inner: quex_core::query(sql),
            marker: PhantomData,
        }
    }

    pub struct QueryScalar<'q, T> {
        inner: quex_core::Query<'q>,
        marker: PhantomData<T>,
    }

    impl<'q, T> QueryScalar<'q, T> {
        pub fn bind<U>(mut self, value: U) -> Self
        where
            U: Encode,
        {
            self.inner = self.inner.bind(value);
            self
        }

        pub async fn fetch_one(self, exec: impl Executor) -> Result<T>
        where
            T: FromRow,
        {
            self.inner.one(exec).await
        }
    }

    pub fn query_scalar<T>(sql: &str) -> QueryScalar<'_, T> {
        QueryScalar {
            inner: quex_core::query(sql),
            marker: PhantomData,
        }
    }
}

#[cfg(feature = "derive")]
pub use qraft_derive::{Cte, FromRow, Insertable, Pivot, Projection, Qraft, alias};

pub mod prelude {
    pub use crate::builder::Insertable;
    pub use crate::query::select;
    pub use crate::{Compatible, DefaultMeta, Qrafting, Query, QueryOf, insert_into, update, with, with_recursive};
    pub use crate::{Decode, Encode, FromRow, FromRowRef};

    #[cfg(feature = "derive")]
    pub use crate::{Cte, Insertable, Pivot, Projection, Qraft, alias};
}