diesel/expression/
count.rs

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