diesel/expression/count.rs
1#[cfg(doc)]
2use super::functions::aggregate_expressions::{
3 AggregateExpressionMethods, WindowExpressionMethods,
4};
5use super::functions::declare_sql_function;
6use super::{Expression, ValidGrouping};
7use crate::backend::Backend;
8use crate::internal::sql_functions::{
9 FunctionFragment, IsWindowFunction, OverClause, WindowFunctionFragment,
10};
11use crate::query_builder::*;
12use crate::result::QueryResult;
13use crate::sql_types::{BigInt, DieselNumericOps, SingleValue, SqlType};
14
15#[declare_sql_function]
16extern "SQL" {
17 /// Creates a SQL `COUNT` expression
18 ///
19 /// As with most bare functions, this is not exported by default. You can import
20 /// it specifically as `diesel::dsl::count`, or glob import
21 /// `diesel::dsl::*`
22 ///
23 /// ## Window Function Usage
24 ///
25 /// This function can be used as window function. See [`WindowExpressionMethods`] for details
26 ///
27 /// ## Aggregate Function Expression
28 ///
29 /// This function can be used as aggregate expression. See [`AggregateExpressionMethods`] for details.
30 ///
31 /// # Examples
32 ///
33 /// ## Normal function usage
34 ///
35 /// ```rust
36 /// # include!("../doctest_setup.rs");
37 /// # use diesel::dsl::*;
38 /// #
39 /// # fn main() {
40 /// # use schema::animals::dsl::*;
41 /// # let connection = &mut establish_connection();
42 /// assert_eq!(Ok(1), animals.select(count(name)).first(connection));
43 /// # }
44 /// ```
45 ///
46 /// ## Window function
47 ///
48 /// ```rust
49 /// # include!("../doctest_setup.rs");
50 /// # use diesel::dsl::*;
51 /// #
52 /// # fn main() {
53 /// # use schema::animals::dsl::*;
54 /// # let connection = &mut establish_connection();
55 /// assert_eq!(
56 /// Ok(1),
57 /// animals
58 /// .select(count(name).partition_by(id))
59 /// .first(connection)
60 /// );
61 /// # }
62 /// ```
63 ///
64 /// ## Aggregate function expression
65 ///
66 /// ```rust
67 /// # include!("../doctest_setup.rs");
68 /// # use diesel::dsl::*;
69 /// #
70 /// # fn main() {
71 /// # use schema::animals::dsl::*;
72 /// # let connection = &mut establish_connection();
73 /// assert_eq!(
74 /// Ok(1),
75 /// animals
76 /// .select(count(name).aggregate_distinct())
77 /// .first(connection)
78 /// );
79 /// # }
80 /// ```
81 #[aggregate]
82 #[window]
83 fn count<T: SqlType + SingleValue>(expr: T) -> BigInt;
84}
85
86/// Creates a SQL `COUNT(*)` expression
87///
88/// For selecting the count of a query, and nothing else, you can just call
89/// [`count`](crate::query_dsl::QueryDsl::count())
90/// on the query instead.
91///
92/// As with most bare functions, this is not exported by default. You can import
93/// it specifically as `diesel::dsl::count_star`, or glob import
94/// `diesel::dsl::*`
95///
96/// # Examples
97///
98/// ```rust
99/// # include!("../doctest_setup.rs");
100/// # use diesel::dsl::*;
101/// #
102/// # fn main() {
103/// # use schema::users::dsl::*;
104/// # let connection = &mut establish_connection();
105/// assert_eq!(Ok(2), users.select(count_star()).first(connection));
106/// # }
107/// ```
108pub fn count_star() -> CountStar {
109 CountStar
110}
111
112#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps, ValidGrouping)]
113#[diesel(aggregate)]
114#[doc(hidden)]
115pub struct CountStar;
116
117impl Expression for CountStar {
118 type SqlType = BigInt;
119}
120
121impl<DB: Backend> FunctionFragment<DB> for CountStar {
122 const FUNCTION_NAME: &'static str = "COUNT";
123
124 fn walk_arguments<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
125 out.push_sql("*");
126 Ok(())
127 }
128}
129
130impl<DB: Backend> QueryFragment<DB> for CountStar {
131 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
132 out.push_sql("COUNT(*)");
133 Ok(())
134 }
135}
136
137impl<Partition, Order, Frame, DB: Backend> WindowFunctionFragment<CountStar, DB>
138 for OverClause<Partition, Order, Frame>
139{
140}
141
142impl IsWindowFunction for CountStar {
143 type ArgTypes = ();
144}
145
146impl_selectable_expression!(CountStar);
147
148#[doc(hidden)]
149#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
150#[deprecated(note = "Use `AggregateExpressionMethods::aggregate_distinct` instead")]
151pub fn count_distinct<T, E>(expr: E) -> CountDistinct<T, E::Expression>
152where
153 T: SqlType + SingleValue,
154 E: crate::expression::AsExpression<T>,
155{
156 use crate::AggregateExpressionMethods;
157
158 count(expr).aggregate_distinct()
159}
160
161#[doc(hidden)]
162#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
163pub type CountDistinct<T, E> = crate::dsl::AggregateDistinct<self::count<T, E>>;