1use std::marker::PhantomData;
2
3use crate::expression::{BinaryOperator, Expression, SelectSubquery, Selection, SelectionExt};
4use crate::query::SelectQuery;
5use crate::schema::Table;
6use crate::value::IntoSqlValue;
7use crate::Column;
8
9#[derive(Clone, Debug)]
10pub struct TypedExpression<V> {
11 expression: Expression,
12 marker: PhantomData<fn() -> V>,
13}
14
15impl<V> TypedExpression<V> {
16 pub(crate) fn new(expression: Expression) -> Self {
17 Self {
18 expression,
19 marker: PhantomData,
20 }
21 }
22
23 pub fn eq(self, value: impl IntoSqlValue<V>) -> Expression {
24 self.compare(BinaryOperator::Eq, value)
25 }
26
27 pub fn ne(self, value: impl IntoSqlValue<V>) -> Expression {
28 self.compare(BinaryOperator::NotEq, value)
29 }
30
31 pub fn gt(self, value: impl IntoSqlValue<V>) -> Expression {
32 self.compare(BinaryOperator::GreaterThan, value)
33 }
34
35 pub fn gte(self, value: impl IntoSqlValue<V>) -> Expression {
36 self.compare(BinaryOperator::GreaterThanOrEq, value)
37 }
38
39 pub fn lt(self, value: impl IntoSqlValue<V>) -> Expression {
40 self.compare(BinaryOperator::LessThan, value)
41 }
42
43 pub fn lte(self, value: impl IntoSqlValue<V>) -> Expression {
44 self.compare(BinaryOperator::LessThanOrEq, value)
45 }
46
47 pub fn over(self) -> crate::WindowExpression<V> {
48 crate::WindowExpression::new(self.expression)
49 }
50
51 pub fn expression(self) -> Expression {
53 self.expression
54 }
55
56 fn compare(self, operator: BinaryOperator, value: impl IntoSqlValue<V>) -> Expression {
57 Expression::Binary {
58 left: Box::new(self.expression),
59 operator,
60 right: Box::new(Expression::Value(value.into_sql_value())),
61 }
62 }
63}
64
65impl<V> Selection for TypedExpression<V> {
66 type Output = V;
67
68 fn expressions(self) -> Vec<Expression> {
69 vec![self.expression]
70 }
71}
72
73impl<V> SelectionExt for TypedExpression<V> {}
74
75pub fn count<T, V>(column: Column<T, V>) -> TypedExpression<i64> {
76 sql_function("count", vec![column.expression()])
77}
78
79pub fn count_all() -> TypedExpression<i64> {
80 sql_function("count", vec![Expression::Wildcard])
81}
82
83pub fn min<T, V>(column: Column<T, V>) -> TypedExpression<V> {
84 sql_function("min", vec![column.expression()])
85}
86
87pub fn max<T, V>(column: Column<T, V>) -> TypedExpression<V> {
88 sql_function("max", vec![column.expression()])
89}
90
91pub fn bound<V>(value: impl IntoSqlValue<V>) -> TypedExpression<V> {
93 TypedExpression::new(Expression::Value(value.into_sql_value()))
94}
95
96pub fn sql_function<V>(
101 name: &'static str,
102 arguments: impl IntoIterator<Item = Expression>,
103) -> TypedExpression<V> {
104 TypedExpression::new(Expression::Function {
105 name,
106 arguments: arguments.into_iter().collect(),
107 })
108}
109
110pub fn coalesce<V>(arguments: impl IntoIterator<Item = Expression>) -> TypedExpression<V> {
112 TypedExpression::new(Expression::Coalesce(arguments.into_iter().collect()))
113}
114
115pub fn least<V>(arguments: impl IntoIterator<Item = Expression>) -> TypedExpression<V> {
117 TypedExpression::new(Expression::Least(arguments.into_iter().collect()))
118}
119
120pub fn cast<From, To>(
125 expression: TypedExpression<From>,
126 sql_type: &'static str,
127) -> TypedExpression<To> {
128 TypedExpression::new(Expression::Cast {
129 expression: Box::new(expression.expression()),
130 sql_type,
131 })
132}
133
134pub fn scalar_subquery<Source: Table, V>(query: SelectQuery<Source, V>) -> TypedExpression<V> {
139 TypedExpression::new(Expression::Subquery(SelectSubquery(Box::new(
140 query.into_node(),
141 ))))
142}