tank-core 0.31.0

Core of Tank: the Rust data layer. This is intended to be used by drivers to implement a backend.
Documentation
use crate::{
    Dataset, Driver, DynQuery, EitherIterator, Expression, ExpressionCollection, NA, SqlWriter,
};
use std::{iter, marker::PhantomData};

pub struct SelectQueryBuilder<Select, From, Where, GroupBy, Having, OrderBy, Limit> {
    pub(crate) select: Select,
    pub(crate) from: Option<From>,
    pub(crate) where_expr: Option<Where>,
    pub(crate) group_by: Option<GroupBy>,
    pub(crate) having: Option<Having>,
    pub(crate) order_by: Option<OrderBy>,
    pub(crate) limit: Option<u32>,
    pub(crate) _l: PhantomData<Limit>,
}

impl<S> SelectQueryBuilder<S, NA, NA, NA, NA, NA, NA> {
    pub fn from<From: Dataset>(
        self,
        from: From,
    ) -> SelectQueryBuilder<S, From, NA, NA, NA, NA, NA> {
        SelectQueryBuilder {
            select: self.select,
            from: Some(from),
            where_expr: Default::default(),
            group_by: Default::default(),
            having: Default::default(),
            order_by: Default::default(),
            limit: Default::default(),
            _l: Default::default(),
        }
    }
}

impl<S, F> SelectQueryBuilder<S, F, NA, NA, NA, NA, NA> {
    pub fn where_expr<Where>(
        self,
        condition: Where,
    ) -> SelectQueryBuilder<S, F, Where, NA, NA, NA, NA>
    where
        Where: Expression,
    {
        SelectQueryBuilder {
            select: self.select,
            from: self.from,
            where_expr: Some(condition),
            group_by: Default::default(),
            having: Default::default(),
            order_by: Default::default(),
            limit: Default::default(),
            _l: Default::default(),
        }
    }
}

impl<S, F, W> SelectQueryBuilder<S, F, W, NA, NA, NA, NA> {
    pub fn group_by<GroupBy>(
        self,
        group_by: GroupBy,
    ) -> SelectQueryBuilder<S, F, W, GroupBy, NA, NA, NA>
    where
        GroupBy: Clone,
    {
        SelectQueryBuilder {
            select: self.select,
            from: self.from,
            where_expr: self.where_expr,
            group_by: Some(group_by),
            having: Default::default(),
            order_by: Default::default(),
            limit: Default::default(),
            _l: Default::default(),
        }
    }
}

impl<S, F, W, G> SelectQueryBuilder<S, F, W, G, NA, NA, NA> {
    pub fn having<Having: Expression>(
        self,
        having: Having,
    ) -> SelectQueryBuilder<S, F, W, G, Having, NA, NA> {
        SelectQueryBuilder {
            select: self.select,
            from: self.from,
            where_expr: self.where_expr,
            group_by: self.group_by,
            having: Some(having),
            order_by: Default::default(),
            limit: Default::default(),
            _l: Default::default(),
        }
    }
}

impl<S, F, W, G, H> SelectQueryBuilder<S, F, W, G, H, NA, NA> {
    pub fn order_by<OrderBy>(
        self,
        order_by: OrderBy,
    ) -> SelectQueryBuilder<S, F, W, G, H, OrderBy, NA> {
        SelectQueryBuilder {
            select: self.select,
            from: self.from,
            where_expr: self.where_expr,
            group_by: self.group_by,
            having: self.having,
            order_by: Some(order_by),
            limit: None,
            _l: Default::default(),
        }
    }
}

impl<S, F, W, G, H, O> SelectQueryBuilder<S, F, W, G, H, O, NA> {
    pub fn limit(self, limit: Option<u32>) -> SelectQueryBuilder<S, F, W, G, H, O, u32> {
        SelectQueryBuilder {
            select: self.select,
            from: self.from,
            where_expr: self.where_expr,
            group_by: self.group_by,
            having: self.having,
            order_by: self.order_by,
            limit,
            _l: Default::default(),
        }
    }
}

impl<S, From, W, G, H, O, L> SelectQueryBuilder<S, From, W, G, H, O, L>
where
    S: ExpressionCollection,
    From: Dataset,
    W: Expression,
    G: ExpressionCollection,
    H: Expression,
    O: ExpressionCollection,
{
    pub fn get_select(&self) -> impl Iterator<Item = impl Expression> + Clone {
        self.select.expr_iter()
    }

    pub fn get_from(&self) -> &Option<From> {
        &self.from
    }

    pub fn get_where(&self) -> &Option<impl Expression> {
        &self.where_expr
    }

    pub fn get_group_by(&self) -> impl Iterator<Item = impl Expression> + Clone {
        match &self.group_by {
            Some(v) => EitherIterator::Left(v.expr_iter()),
            None => EitherIterator::Right(iter::empty()),
        }
    }

    pub fn get_having(&self) -> &Option<impl Expression> {
        &self.having
    }

    pub fn get_order_by(&self) -> impl Iterator<Item = impl Expression> + Clone {
        match &self.order_by {
            Some(v) => EitherIterator::Left(v.expr_iter()),
            None => EitherIterator::Right(iter::empty()),
        }
    }

    pub fn get_limit(&self) -> Option<u32> {
        self.limit
    }

    pub fn build<D: Driver>(&self, driver: &D) -> DynQuery {
        let writer = driver.sql_writer();
        let mut query = DynQuery::default();
        writer.write_select(&mut query, self);
        query.into()
    }

    pub fn build_into<D: Driver>(&self, driver: &D, out: &mut DynQuery) {
        let writer = driver.sql_writer();
        writer.write_select(out, self);
    }
}

/// SELECT query builder.
///
/// Use `QueryBuilder::new().select(..)` to start.
pub trait SelectQuery<From>
where
    From: Dataset,
{
    /// Get SELECT expressions.
    fn get_select(&self) -> impl Iterator<Item = impl Expression> + Clone;
    /// Get FROM clause dataset.
    fn get_from<'s>(&'s self) -> &'s Option<From>;
    /// Get WHERE clause expression.
    fn get_where<'s>(&'s self) -> &'s Option<impl Expression>;
    /// Get GROUP BY expressions.
    fn get_group_by(&self) -> impl Iterator<Item = impl Expression> + Clone;
    /// Get HAVING clause expression.
    fn get_having(&self) -> &Option<impl Expression>;
    /// Get ORDER BY expressions.
    fn get_order_by(&self) -> impl Iterator<Item = impl Expression> + Clone;
    /// Get LIMIT value.
    fn get_limit(&self) -> Option<u32>;
    /// Build query.
    fn build<D: Driver>(&self, driver: &D) -> DynQuery;
    /// Build query into existing buffer.
    fn build_into<D: Driver>(&self, driver: &D, out: &mut DynQuery);
}

impl<S, From, W, G, H, O, L> SelectQuery<From> for SelectQueryBuilder<S, From, W, G, H, O, L>
where
    S: ExpressionCollection,
    From: Dataset,
    W: Expression,
    G: ExpressionCollection,
    H: Expression,
    O: ExpressionCollection,
{
    fn get_select(&self) -> impl Iterator<Item = impl Expression> + Clone {
        self.get_select()
    }

    fn get_from(&self) -> &Option<From> {
        self.get_from()
    }

    fn get_where(&self) -> &Option<impl Expression> {
        self.get_where()
    }

    fn get_group_by(&self) -> impl Iterator<Item = impl Expression> + Clone {
        self.get_group_by()
    }

    fn get_having(&self) -> &Option<impl Expression> {
        self.get_having()
    }

    fn get_order_by(&self) -> impl Iterator<Item = impl Expression> + Clone {
        self.get_order_by()
    }

    fn get_limit(&self) -> Option<u32> {
        self.get_limit()
    }

    fn build<D: Driver>(&self, driver: &D) -> DynQuery {
        self.build(driver)
    }

    fn build_into<D: Driver>(&self, driver: &D, out: &mut DynQuery) {
        self.build_into(driver, out);
    }
}