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 expr(&self) -> String {
51 match self {
52 Count(col, distinct) => {
53 let col_name = E::format_column(col);
54 let field = Query::format_field(&col_name);
55 if *distinct {
56 format!("count(distinct {field})")
57 } else {
58 format!("count({field})")
59 }
60 }
61 Sum(col) => {
62 let col_name = E::format_column(col);
63 let field = Query::format_field(&col_name);
64 format!("sum({field})")
65 }
66 Avg(col) => {
67 let col_name = E::format_column(col);
68 let field = Query::format_field(&col_name);
69 format!("avg({field})")
70 }
71 Min(col) => {
72 let col_name = E::format_column(col);
73 let field = Query::format_field(&col_name);
74 format!("min({field})")
75 }
76 Max(col) => {
77 let col_name = E::format_column(col);
78 let field = Query::format_field(&col_name);
79 format!("max({field})")
80 }
81 Stddev(col) => {
82 let col_name = E::format_column(col);
83 let field = Query::format_field(&col_name);
84 format!("stddev({field})")
85 }
86 Variance(col) => {
87 let col_name = E::format_column(col);
88 let field = Query::format_field(&col_name);
89 format!("variance({field})")
90 }
91 JsonArrayagg(col) => {
92 let col_name = E::format_column(col);
93 let field = Query::format_field(&col_name);
94 if cfg!(any(
95 feature = "orm-mariadb",
96 feature = "orm-mysql",
97 feature = "orm-tidb"
98 )) {
99 format!("json_arrayagg({field})")
100 } else if cfg!(feature = "orm-postgres") {
101 format!("jsonb_agg({field})")
102 } else {
103 format!("json_group_array({field})")
104 }
105 }
106 JsonObjectagg(key_col, val_col) => {
107 let key_col_name = E::format_column(key_col);
108 let val_col_name = E::format_column(val_col);
109 let key_field = Query::format_field(&key_col_name);
110 let val_field = Query::format_field(&val_col_name);
111 if cfg!(any(
112 feature = "orm-mariadb",
113 feature = "orm-mysql",
114 feature = "orm-tidb"
115 )) {
116 format!("json_objectagg({key_field}, {val_field})")
117 } else if cfg!(feature = "orm-postgres") {
118 format!("jsonb_object_agg({key_field}, {val_field})")
119 } else {
120 format!("json_group_object({key_field}, {val_field})")
121 }
122 }
123 }
124 }
125}