1use crate::{
4 alias::Aliased,
5 expression::Expression,
6 lower::LowerCtx,
7 query::{LowerHaving, LowerProject, Star},
8};
9
10pub trait LowerAggregate {
12 fn lower_aggregate(self, ctx: &mut LowerCtx);
13}
14
15impl<E> LowerAggregate for E
16where
17 E: Expression,
18{
19 fn lower_aggregate(self, ctx: &mut LowerCtx) {
20 let _ = self.lower(ctx);
21 }
22}
23
24pub trait LowerCount {
26 fn lower_count(self, ctx: &mut LowerCtx);
27}
28
29impl<E> LowerCount for E
30where
31 E: LowerAggregate,
32{
33 fn lower_count(self, ctx: &mut LowerCtx) {
34 E::lower_aggregate(self, ctx);
35 }
36}
37
38impl LowerCount for Star {
39 fn lower_count(self, ctx: &mut LowerCtx) {
40 let _ = ctx.lower_star();
41 }
42}
43
44#[derive(Debug, Clone, Copy)]
46pub struct Count<E> {
47 inner: E,
48}
49
50impl<E: LowerCount> Count<E> {
51 fn lower(self, ctx: &mut LowerCtx) -> usize {
52 self.inner.lower_count(ctx);
53 ctx.lower_fn("count", 1)
54 }
55}
56
57#[derive(Debug, Clone, Copy)]
59pub struct Aggregate<E> {
60 inner: E,
61 name: &'static str,
62}
63
64impl<E: LowerAggregate> Aggregate<E> {
65 fn lower(self, ctx: &mut LowerCtx) -> usize {
66 self.inner.lower_aggregate(ctx);
67 ctx.lower_fn(self.name, 1)
68 }
69}
70
71pub fn count<E>(e: E) -> Count<E>
73where
74 E: LowerCount,
75{
76 Count { inner: e }
77}
78
79pub fn max<E>(e: E) -> Aggregate<E>
81where
82 E: LowerAggregate,
83{
84 Aggregate {
85 inner: e,
86 name: "max",
87 }
88}
89
90pub fn min<E>(e: E) -> Aggregate<E>
92where
93 E: LowerAggregate,
94{
95 Aggregate {
96 inner: e,
97 name: "min",
98 }
99}
100
101pub fn sum<E>(e: E) -> Aggregate<E>
103where
104 E: LowerAggregate,
105{
106 Aggregate {
107 inner: e,
108 name: "sum",
109 }
110}
111
112pub fn avg<E>(e: E) -> Aggregate<E>
114where
115 E: LowerAggregate,
116{
117 Aggregate {
118 inner: e,
119 name: "avg",
120 }
121}
122
123impl<E: LowerCount> LowerProject for Count<E> {
124 fn lower_project(self, ctx: &mut LowerCtx) {
125 self.lower(ctx);
126 }
127}
128
129impl<E: LowerCount> LowerHaving for Count<E> {
130 fn lower_having(self, ctx: &mut LowerCtx) {
131 self.lower(ctx);
132 }
133}
134
135impl<E: LowerCount> LowerProject for Aliased<Count<E>> {
136 fn lower_project(self, ctx: &mut LowerCtx) {
137 let inner = self.inner.lower(ctx);
138 let _ = ctx.lower_alias(self.alias, inner);
139 }
140}
141
142impl<E: LowerAggregate> LowerProject for Aliased<Aggregate<E>> {
143 fn lower_project(self, ctx: &mut LowerCtx) {
144 let inner = self.inner.lower(ctx);
145 let _ = ctx.lower_alias(self.alias, inner);
146 }
147}
148
149impl<E: LowerAggregate> LowerProject for Aggregate<E> {
150 fn lower_project(self, ctx: &mut LowerCtx) {
151 self.lower(ctx);
152 }
153}