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}