diesel/expression/functions/
aggregate_ordering.rs

1use self::private::SqlOrdAggregate;
2#[cfg(doc)]
3use super::aggregate_expressions::{AggregateExpressionMethods, WindowExpressionMethods};
4use crate::expression::functions::declare_sql_function;
5
6#[declare_sql_function]
7extern "SQL" {
8    /// Represents a SQL `MAX` function. This function can only take types which are
9    /// ordered.
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(8)), animals.select(max(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, max(legs).partition_by(id)))
45    ///     .load::<(Option<String>, Option<i32>)>(connection);
46    ///
47    /// assert_eq!(
48    ///     Ok(vec![(Some("Jack".into()), Some(4)), (None, Some(8))]),
49    ///     res
50    /// );
51    /// # }
52    /// ```
53    ///
54    ///
55    /// ## Aggregate function expression
56    ///
57    /// ```rust
58    /// # include!("../../doctest_setup.rs");
59    /// # use diesel::dsl::*;
60    /// #
61    /// # fn main() {
62    /// #     use schema::animals::dsl::*;
63    /// #     let connection = &mut establish_connection();
64    /// #     #[cfg(not(feature = "mysql"))]
65    /// assert_eq!(
66    ///     Ok(Some(4)),
67    ///     animals
68    ///         .select(max(legs).aggregate_filter(legs.lt(8)))
69    ///         .first(connection)
70    /// );
71    /// # }
72    /// ```
73    #[aggregate]
74    #[window]
75    fn max<ST: SqlOrdAggregate>(expr: ST) -> ST::Ret;
76
77    /// Represents a SQL `MIN` function. This function can only take types which are
78    /// ordered.
79    ///
80    /// ## Window Function Usage
81    ///
82    /// This function can be used as window function. See [`WindowExpressionMethods`] for details
83    ///
84    /// ## Aggregate Function Expression
85    ///
86    /// This function can be used as aggregate expression. See [`AggregateExpressionMethods`] for details.
87    ///
88    /// # Examples
89    ///
90    /// ## Normal function usage
91    ///
92    /// ```rust
93    /// # include!("../../doctest_setup.rs");
94    /// # use diesel::dsl::*;
95    /// #
96    /// # fn main() {
97    /// #     use schema::animals::dsl::*;
98    /// #     let connection = &mut establish_connection();
99    /// assert_eq!(Ok(Some(4)), animals.select(min(legs)).first(connection));
100    /// # }
101    /// ```
102    ///
103    /// ## Window function
104    ///
105    /// ```rust
106    /// # include!("../../doctest_setup.rs");
107    /// # use diesel::dsl::*;
108    /// #
109    /// # fn main() {
110    /// #     use schema::animals::dsl::*;
111    /// #     let connection = &mut establish_connection();
112    /// let res = animals
113    ///     .select((name, min(legs).partition_by(id)))
114    ///     .load::<(Option<String>, Option<i32>)>(connection);
115    ///
116    /// assert_eq!(
117    ///     Ok(vec![(Some("Jack".into()), Some(4)), (None, Some(8))]),
118    ///     res
119    /// );
120    /// # }
121    /// ```
122    ///
123    /// ## Aggregate function expression
124    ///
125    /// ```rust
126    /// # include!("../../doctest_setup.rs");
127    /// # use diesel::dsl::*;
128    /// #
129    /// # fn main() {
130    /// #     use schema::animals::dsl::*;
131    /// #     let connection = &mut establish_connection();
132    /// #     #[cfg(not(feature = "mysql"))]
133    /// assert_eq!(
134    ///     Ok(Some(8)),
135    ///     animals
136    ///         .select(min(legs).aggregate_filter(legs.gt(4)))
137    ///         .first(connection)
138    /// );
139    /// # }
140    /// ```
141    #[aggregate]
142    #[window]
143    fn min<ST: SqlOrdAggregate>(expr: ST) -> ST::Ret;
144}
145
146mod private {
147    use crate::sql_types::{IntoNullable, SingleValue, SqlOrd, SqlType};
148    pub trait SqlOrdAggregate: SingleValue {
149        type Ret: SqlType + SingleValue;
150    }
151
152    impl<T> SqlOrdAggregate for T
153    where
154        T: SqlOrd + IntoNullable + SingleValue,
155        T::Nullable: SqlType + SingleValue,
156    {
157        type Ret = T::Nullable;
158    }
159}