use std::marker::PhantomData;
use crate::expression::{BinaryOperator, Expression, SelectSubquery, Selection, SelectionExt};
use crate::query::SelectQuery;
use crate::schema::Table;
use crate::value::IntoSqlValue;
use crate::Column;
#[derive(Clone, Debug)]
pub struct TypedExpression<V> {
expression: Expression,
marker: PhantomData<fn() -> V>,
}
impl<V> TypedExpression<V> {
pub(crate) fn new(expression: Expression) -> Self {
Self {
expression,
marker: PhantomData,
}
}
pub fn eq(self, value: impl IntoSqlValue<V>) -> Expression {
self.compare(BinaryOperator::Eq, value)
}
pub fn ne(self, value: impl IntoSqlValue<V>) -> Expression {
self.compare(BinaryOperator::NotEq, value)
}
pub fn gt(self, value: impl IntoSqlValue<V>) -> Expression {
self.compare(BinaryOperator::GreaterThan, value)
}
pub fn gte(self, value: impl IntoSqlValue<V>) -> Expression {
self.compare(BinaryOperator::GreaterThanOrEq, value)
}
pub fn lt(self, value: impl IntoSqlValue<V>) -> Expression {
self.compare(BinaryOperator::LessThan, value)
}
pub fn lte(self, value: impl IntoSqlValue<V>) -> Expression {
self.compare(BinaryOperator::LessThanOrEq, value)
}
pub fn over(self) -> crate::WindowExpression<V> {
crate::WindowExpression::new(self.expression)
}
pub fn expression(self) -> Expression {
self.expression
}
fn compare(self, operator: BinaryOperator, value: impl IntoSqlValue<V>) -> Expression {
Expression::Binary {
left: Box::new(self.expression),
operator,
right: Box::new(Expression::Value(value.into_sql_value())),
}
}
}
impl<V> Selection for TypedExpression<V> {
type Output = V;
fn expressions(self) -> Vec<Expression> {
vec![self.expression]
}
}
impl<V> SelectionExt for TypedExpression<V> {}
pub fn count<T, V>(column: Column<T, V>) -> TypedExpression<i64> {
sql_function("count", vec![column.expression()])
}
pub fn count_all() -> TypedExpression<i64> {
sql_function("count", vec![Expression::Wildcard])
}
pub fn min<T, V>(column: Column<T, V>) -> TypedExpression<V> {
sql_function("min", vec![column.expression()])
}
pub fn max<T, V>(column: Column<T, V>) -> TypedExpression<V> {
sql_function("max", vec![column.expression()])
}
pub fn bound<V>(value: impl IntoSqlValue<V>) -> TypedExpression<V> {
TypedExpression::new(Expression::Value(value.into_sql_value()))
}
pub fn sql_function<V>(
name: &'static str,
arguments: impl IntoIterator<Item = Expression>,
) -> TypedExpression<V> {
TypedExpression::new(Expression::Function {
name,
arguments: arguments.into_iter().collect(),
})
}
pub fn coalesce<V>(arguments: impl IntoIterator<Item = Expression>) -> TypedExpression<V> {
TypedExpression::new(Expression::Coalesce(arguments.into_iter().collect()))
}
pub fn least<V>(arguments: impl IntoIterator<Item = Expression>) -> TypedExpression<V> {
TypedExpression::new(Expression::Least(arguments.into_iter().collect()))
}
pub fn cast<From, To>(
expression: TypedExpression<From>,
sql_type: &'static str,
) -> TypedExpression<To> {
TypedExpression::new(Expression::Cast {
expression: Box::new(expression.expression()),
sql_type,
})
}
pub fn scalar_subquery<Source: Table, V>(query: SelectQuery<Source, V>) -> TypedExpression<V> {
TypedExpression::new(Expression::Subquery(SelectSubquery(Box::new(
query.into_node(),
))))
}