1use std::{
2 marker::PhantomData,
3 ops::{Deref, DerefMut},
4 rc::Rc,
5};
6
7use ref_cast::RefCast;
8use sea_query::{Func, SelectStatement, SimpleExpr};
9
10use crate::{
11 Expr, Table,
12 alias::MyAlias,
13 rows::Rows,
14 value::{EqTyp, IntoExpr, MyTyp, NumTyp, Typed, ValueBuilder},
15};
16
17use super::DynTypedExpr;
18
19pub struct Aggregate<'outer, 'inner, S> {
21 pub(crate) query: Rows<'inner, S>,
22 _p: PhantomData<&'inner &'outer ()>,
23}
24
25impl<'inner, S> Deref for Aggregate<'_, 'inner, S> {
26 type Target = Rows<'inner, S>;
27
28 fn deref(&self) -> &Self::Target {
29 &self.query
30 }
31}
32
33impl<S> DerefMut for Aggregate<'_, '_, S> {
34 fn deref_mut(&mut self) -> &mut Self::Target {
35 &mut self.query
36 }
37}
38
39impl<'outer, 'inner, S: 'static> Aggregate<'outer, 'inner, S> {
40 fn select<T>(
41 &self,
42 expr: impl 'static + Fn(&mut ValueBuilder) -> SimpleExpr,
43 ) -> Aggr<S, Option<T>> {
44 let expr = DynTypedExpr(Rc::new(expr));
45 let mut builder = self.query.ast.clone().full();
46 let (select, mut fields) = builder.build_select(true, vec![expr]);
47
48 let conds = builder.forwarded.into_iter().map(|x| x.1.1).collect();
49
50 Aggr {
51 _p2: PhantomData,
52 select: Rc::new(select),
53 field: {
54 debug_assert_eq!(fields.len(), 1);
55 fields.swap_remove(0)
56 },
57 conds,
58 }
59 }
60
61 #[deprecated = "Please use `Rows::filter` instead"]
63 pub fn filter_on<T: EqTyp + 'static>(
64 &mut self,
65 val: impl IntoExpr<'inner, S, Typ = T>,
66 on: impl IntoExpr<'outer, S, Typ = T>,
67 ) {
68 let on = on.into_expr();
69 self.filter(val.into_expr().eq(on))
70 }
71
72 pub fn avg(&self, val: impl IntoExpr<'inner, S, Typ = f64>) -> Expr<'outer, S, Option<f64>> {
74 let val = val.into_expr().inner;
75 Expr::new(self.select(move |b| Func::avg(val.build_expr(b)).into()))
76 }
77
78 pub fn max<T>(&self, val: impl IntoExpr<'inner, S, Typ = T>) -> Expr<'outer, S, Option<T>>
80 where
81 T: NumTyp,
82 {
83 let val = val.into_expr().inner;
84 Expr::new(self.select(move |b| Func::max(val.build_expr(b)).into()))
85 }
86
87 pub fn min<T>(&self, val: impl IntoExpr<'inner, S, Typ = T>) -> Expr<'outer, S, Option<T>>
89 where
90 T: NumTyp,
91 {
92 let val = val.into_expr().inner;
93 Expr::new(self.select(move |b| Func::min(val.build_expr(b)).into()))
94 }
95
96 pub fn sum<T>(&self, val: impl IntoExpr<'inner, S, Typ = T>) -> Expr<'outer, S, T>
98 where
99 T: NumTyp,
100 {
101 let val = val.into_expr().inner;
102 let val = self.select::<T>(move |b| Func::sum(val.build_expr(b)).into());
103
104 Expr::adhoc(move |b| {
105 sea_query::Expr::expr(val.build_expr(b))
106 .if_null(SimpleExpr::Constant(T::ZERO.into_sea_value()))
107 })
108 }
109
110 pub fn count_distinct<T: EqTyp + 'static>(
112 &self,
113 val: impl IntoExpr<'inner, S, Typ = T>,
114 ) -> Expr<'outer, S, i64> {
115 let val = val.into_expr().inner;
116 let val = self.select::<i64>(move |b| Func::count_distinct(val.build_expr(b)).into());
117 Expr::adhoc(move |b| {
118 sea_query::Expr::expr(val.build_expr(b))
119 .if_null(SimpleExpr::Constant(0i64.into_sea_value()))
120 })
121 }
122
123 pub fn exists(&self) -> Expr<'outer, S, bool> {
125 let val = self.select::<i64>(|_| SimpleExpr::Constant(1.into_sea_value()));
126 Expr::adhoc(move |b| sea_query::Expr::expr(val.build_expr(b)).is_not_null())
127 }
128}
129
130pub struct Aggr<S, T> {
131 pub(crate) _p2: PhantomData<(S, T)>,
132 pub(crate) select: Rc<SelectStatement>,
133 pub(crate) conds: Vec<DynTypedExpr>,
134 pub(crate) field: MyAlias,
135}
136
137impl<S, T> Clone for Aggr<S, T> {
138 fn clone(&self) -> Self {
139 Self {
140 _p2: PhantomData,
141 select: self.select.clone(),
142 conds: self.conds.clone(),
143 field: self.field,
144 }
145 }
146}
147
148impl<S, T: MyTyp> Typed for Aggr<S, T> {
149 type Typ = T;
150 fn build_expr(&self, b: &mut ValueBuilder) -> SimpleExpr {
151 sea_query::Expr::col((self.build_table(b), self.field)).into()
152 }
153}
154
155impl<S, T> Aggr<S, T> {
156 fn build_table(&self, b: &mut ValueBuilder) -> MyAlias {
157 let conds = self.conds.iter().map(|expr| (expr.0)(b)).collect();
158 b.get_aggr(self.select.clone(), conds)
159 }
160}
161
162impl<S, T: Table> Deref for Aggr<S, T> {
163 type Target = T::Ext<Self>;
164
165 fn deref(&self) -> &Self::Target {
166 RefCast::ref_cast(self)
167 }
168}
169
170pub fn aggregate<'outer, S, F, R>(f: F) -> R
187where
188 F: for<'inner> FnOnce(&mut Aggregate<'outer, 'inner, S>) -> R,
189{
190 let inner = Rows {
191 phantom: PhantomData,
192 ast: Default::default(),
193 _p: PhantomData,
194 };
195 let mut group = Aggregate {
196 query: inner,
197 _p: PhantomData,
198 };
199 f(&mut group)
200}