1use self::Aggregation::*;
2use super::{Entity, query::QueryExt};
3use zino_core::model::Query;
4
5#[derive(Debug, Clone, Copy)]
26#[non_exhaustive]
27pub enum Aggregation<E: Entity> {
28 Count(E::Column, bool),
30 Sum(E::Column),
32 Avg(E::Column),
34 Min(E::Column),
36 Max(E::Column),
38 Stddev(E::Column),
40 Variance(E::Column),
42 JsonArrayagg(E::Column),
44 JsonObjectagg(E::Column, E::Column),
46}
47
48impl<E: Entity> Aggregation<E> {
49 pub(super) fn default_alias(&self) -> String {
51 match self {
52 Count(col, distinct) => {
53 if *distinct {
54 [col.as_ref(), "_distinct"].concat()
55 } else {
56 [col.as_ref(), "_count"].concat()
57 }
58 }
59 Sum(col) => [col.as_ref(), "_sum"].concat(),
60 Avg(col) => [col.as_ref(), "_avg"].concat(),
61 Min(col) => [col.as_ref(), "_min"].concat(),
62 Max(col) => [col.as_ref(), "_max"].concat(),
63 Stddev(col) => [col.as_ref(), "_stddev"].concat(),
64 Variance(col) => [col.as_ref(), "_variance"].concat(),
65 JsonArrayagg(col) => [col.as_ref(), "_arrayagg"].concat(),
66 JsonObjectagg(key_col, val_col) => {
67 [key_col.as_ref(), "_", val_col.as_ref(), "_objectagg"].concat()
68 }
69 }
70 }
71
72 pub(super) fn expr(&self) -> String {
74 match self {
75 Count(col, distinct) => {
76 let col_name = E::format_column(col);
77 let field = Query::format_field(&col_name);
78 if *distinct {
79 format!("count(distinct {field})")
80 } else {
81 format!("count({field})")
82 }
83 }
84 Sum(col) => {
85 let col_name = E::format_column(col);
86 let field = Query::format_field(&col_name);
87 format!("sum({field})")
88 }
89 Avg(col) => {
90 let col_name = E::format_column(col);
91 let field = Query::format_field(&col_name);
92 format!("avg({field})")
93 }
94 Min(col) => {
95 let col_name = E::format_column(col);
96 let field = Query::format_field(&col_name);
97 format!("min({field})")
98 }
99 Max(col) => {
100 let col_name = E::format_column(col);
101 let field = Query::format_field(&col_name);
102 format!("max({field})")
103 }
104 Stddev(col) => {
105 let col_name = E::format_column(col);
106 let field = Query::format_field(&col_name);
107 format!("stddev({field})")
108 }
109 Variance(col) => {
110 let col_name = E::format_column(col);
111 let field = Query::format_field(&col_name);
112 format!("variance({field})")
113 }
114 JsonArrayagg(col) => {
115 let col_name = E::format_column(col);
116 let field = Query::format_field(&col_name);
117 if cfg!(any(
118 feature = "orm-mariadb",
119 feature = "orm-mysql",
120 feature = "orm-tidb"
121 )) {
122 format!("json_arrayagg({field})")
123 } else if cfg!(feature = "orm-postgres") {
124 format!("jsonb_agg({field})")
125 } else {
126 format!("json_group_array({field})")
127 }
128 }
129 JsonObjectagg(key_col, val_col) => {
130 let key_col_name = E::format_column(key_col);
131 let val_col_name = E::format_column(val_col);
132 let key_field = Query::format_field(&key_col_name);
133 let val_field = Query::format_field(&val_col_name);
134 if cfg!(any(
135 feature = "orm-mariadb",
136 feature = "orm-mysql",
137 feature = "orm-tidb"
138 )) {
139 format!("json_objectagg({key_field}, {val_field})")
140 } else if cfg!(feature = "orm-postgres") {
141 format!("jsonb_object_agg({key_field}, {val_field})")
142 } else {
143 format!("json_group_object({key_field}, {val_field})")
144 }
145 }
146 }
147 }
148}