diesel/expression/functions/aggregate_folding.rs
1#[cfg(doc)]
2use super::aggregate_expressions::{AggregateExpressionMethods, WindowExpressionMethods};
3use crate::expression::functions::declare_sql_function;
4use crate::sql_types::Foldable;
5
6#[declare_sql_function]
7extern "SQL" {
8 /// Represents a SQL `SUM` function. This function can only take types which are
9 /// Foldable.
10 ///
11 /// ## Window Function Usage
12 ///
13 /// This function can be used as window function. See [`WindowExpressionMethods`] for details
14 ///
15 /// ## Aggregate Function Expression
16 ///
17 /// This function can be used as aggregate expression. See [`AggregateExpressionMethods`] for details.
18 ///
19 /// # Examples
20 ///
21 /// ## Normal function usage
22 ///
23 /// ```rust
24 /// # include!("../../doctest_setup.rs");
25 /// # use diesel::dsl::*;
26 /// #
27 /// # fn main() {
28 /// # use schema::animals::dsl::*;
29 /// # let connection = &mut establish_connection();
30 /// assert_eq!(Ok(Some(12i64)), animals.select(sum(legs)).first(connection));
31 /// # }
32 /// ```
33 ///
34 /// ## Window function
35 ///
36 /// ```rust
37 /// # include!("../../doctest_setup.rs");
38 /// # use diesel::dsl::*;
39 /// #
40 /// # fn main() {
41 /// # use schema::animals::dsl::*;
42 /// # let connection = &mut establish_connection();
43 /// let res = animals
44 /// .select((name, sum(legs).partition_by(id)))
45 /// .load::<(Option<String>, Option<i64>)>(connection);
46 ///
47 /// assert_eq!(
48 /// Ok(vec![(Some("Jack".into()), Some(4)), (None, Some(8))]),
49 /// res
50 /// );
51 /// # }
52 /// ```
53 ///
54 /// ## Aggregate function expression
55 ///
56 /// ```rust
57 /// # include!("../../doctest_setup.rs");
58 /// # use diesel::dsl::*;
59 /// #
60 /// # fn main() {
61 /// # use schema::animals::dsl::*;
62 /// # let connection = &mut establish_connection();
63 /// # #[cfg(not(feature = "mysql"))]
64 /// assert_eq!(
65 /// Ok(Some(4i64)),
66 /// animals
67 /// .select(sum(legs).aggregate_filter(legs.lt(8)))
68 /// .first(connection)
69 /// );
70 /// # }
71 /// ```
72 #[aggregate]
73 #[window]
74 fn sum<ST: Foldable>(expr: ST) -> ST::Sum;
75
76 /// Represents a SQL `AVG` function. This function can only take types which are
77 /// Foldable.
78 ///
79 /// ## Window Function Usage
80 ///
81 /// This function can be used as window function. See [`WindowExpressionMethods`] for details
82 ///
83 /// ## Aggregate Function Expression
84 ///
85 /// This function can be used as aggregate expression. See [`AggregateExpressionMethods`] for details.
86 ///
87 /// # Examples
88 ///
89 /// ## Normal function usage
90 ///
91 /// ```rust
92 /// # include!("../../doctest_setup.rs");
93 /// # use diesel::dsl::*;
94 /// # #[cfg(feature = "numeric")]
95 /// # extern crate bigdecimal;
96 /// #
97 /// # fn main() {
98 /// # run_test().unwrap();
99 /// # }
100 /// #
101 /// # table! {
102 /// # numbers (number) {
103 /// # number -> Integer,
104 /// # }
105 /// # }
106 /// #
107 /// # #[cfg(all(feature = "numeric", any(feature = "postgres", not(feature = "sqlite"))))]
108 /// # fn run_test() -> QueryResult<()> {
109 /// # use bigdecimal::BigDecimal;
110 /// # use self::numbers::dsl::*;
111 /// # let conn = &mut establish_connection();
112 /// # diesel::sql_query("CREATE TEMPORARY TABLE numbers (number INTEGER)").execute(conn)?;
113 /// diesel::insert_into(numbers)
114 /// .values(&vec![number.eq(1), number.eq(2)])
115 /// .execute(conn)?;
116 /// let average = numbers.select(avg(number)).get_result(conn)?;
117 /// let expected = "1.5".parse::<BigDecimal>().unwrap();
118 /// assert_eq!(Some(expected), average);
119 /// # Ok(())
120 /// # }
121 /// #
122 /// # #[cfg(not(all(feature = "numeric", any(feature = "postgres", not(feature = "sqlite")))))]
123 /// # fn run_test() -> QueryResult<()> {
124 /// # Ok(())
125 /// # }
126 /// ```
127 ///
128 /// ## Window function
129 ///
130 /// ```rust
131 /// # include!("../../doctest_setup.rs");
132 /// # use diesel::dsl::*;
133 /// #
134 /// # fn main() {
135 /// # run_test().unwrap();
136 /// # }
137 /// #
138 /// # #[cfg(not(all(feature = "numeric", feature = "postgres")))]
139 /// # fn run_test() -> QueryResult<()> {
140 /// # Ok(())
141 /// # }
142 /// # #[cfg(all(feature = "numeric", feature = "postgres"))]
143 /// fn run_test() -> QueryResult<()> {
144 /// # use schema::animals::dsl::*;
145 /// # use bigdecimal::BigDecimal;
146 /// # let connection = &mut establish_connection();
147 /// let res = animals.select((name, avg(legs).partition_by(id))).load::<(Option<String>, Option<BigDecimal>)>(connection)?;
148 ///
149 /// assert_eq!(vec![
150 /// (Some("Jack".into()), "4".parse::<BigDecimal>().ok()),
151 /// (None, "8".parse::<BigDecimal>().ok()),
152 /// ], res);
153 /// # Ok(())
154 /// # }
155 /// ```
156 ///
157 /// ## Aggregate function expression
158 ///
159 /// ```rust
160 /// # include!("../../doctest_setup.rs");
161 /// # use diesel::dsl::*;
162 /// # #[cfg(feature = "numeric")]
163 /// # extern crate bigdecimal;
164 /// #
165 /// # fn main() {
166 /// # run_test().unwrap();
167 /// # }
168 /// #
169 /// # table! {
170 /// # numbers (number) {
171 /// # number -> Integer,
172 /// # }
173 /// # }
174 /// #
175 /// # #[cfg(all(feature = "numeric", feature = "postgres"))]
176 /// # fn run_test() -> QueryResult<()> {
177 /// # use bigdecimal::BigDecimal;
178 /// # use self::numbers::dsl::*;
179 /// # let conn = &mut establish_connection();
180 /// # diesel::sql_query("CREATE TEMPORARY TABLE numbers (number INTEGER)").execute(conn)?;
181 /// diesel::insert_into(numbers)
182 /// .values(&vec![number.eq(1), number.eq(2), number.eq(3)])
183 /// .execute(conn)?;
184 ///
185 /// let average = numbers.select(avg(number).aggregate_filter(number.lt(3))).get_result(conn)?;
186 /// let expected = "1.5".parse::<BigDecimal>().unwrap();
187 /// assert_eq!(Some(expected), average);
188 /// # Ok(())
189 /// # }
190 /// #
191 /// # #[cfg(not(all(feature = "numeric", feature = "postgres")))]
192 /// # fn run_test() -> QueryResult<()> {
193 /// # Ok(())
194 /// # }
195 #[aggregate]
196 #[window]
197 fn avg<ST: Foldable>(expr: ST) -> ST::Avg;
198}