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#[doc(hidden)]
#[allow(non_camel_case_types, non_snake_case, unused_imports)]
pub(crate) mod avg_utils {
    use diesel::{self, QueryResult};
    use diesel::expression::{
        AsExpression, Expression, SelectableExpression, AppearsOnTable,
        ValidGrouping,
    };
    use diesel::query_builder::{QueryFragment, AstPass};
    use diesel::sql_types::*;
    use diesel::internal::sql_functions::*;
    use super::*;
    pub struct avg<ST, expr> {
        pub(in super) expr: expr,
        pub(in super) ST: ::std::marker::PhantomData<ST>,
    }
    const _: () =
        {
            use diesel;
            use diesel::internal::derives::numeric_ops as ops;
            use diesel::expression::{Expression, AsExpression};
            use diesel::sql_types::ops::{Add, Sub, Mul, Div};
            use diesel::sql_types::{SqlType, SingleValue};
            impl<ST, expr, __Rhs> ::std::ops::Add<__Rhs> for avg<ST, expr>
                where Self: Expression, Self: Expression,
                <Self as Expression>::SqlType: Add,
                <<Self as Expression>::SqlType as Add>::Rhs: SqlType +
                SingleValue,
                __Rhs: AsExpression<<<Self as Expression>::SqlType as
                Add>::Rhs> {
                type Output = ops::Add<Self, __Rhs::Expression>;
                fn add(self, rhs: __Rhs) -> Self::Output {
                    ops::Add::new(self, rhs.as_expression())
                }
            }
            impl<ST, expr, __Rhs> ::std::ops::Sub<__Rhs> for avg<ST, expr>
                where Self: Expression, Self: Expression,
                <Self as Expression>::SqlType: Sub,
                <<Self as Expression>::SqlType as Sub>::Rhs: SqlType +
                SingleValue,
                __Rhs: AsExpression<<<Self as Expression>::SqlType as
                Sub>::Rhs> {
                type Output = ops::Sub<Self, __Rhs::Expression>;
                fn sub(self, rhs: __Rhs) -> Self::Output {
                    ops::Sub::new(self, rhs.as_expression())
                }
            }
            impl<ST, expr, __Rhs> ::std::ops::Mul<__Rhs> for avg<ST, expr>
                where Self: Expression, Self: Expression,
                <Self as Expression>::SqlType: Mul,
                <<Self as Expression>::SqlType as Mul>::Rhs: SqlType +
                SingleValue,
                __Rhs: AsExpression<<<Self as Expression>::SqlType as
                Mul>::Rhs> {
                type Output = ops::Mul<Self, __Rhs::Expression>;
                fn mul(self, rhs: __Rhs) -> Self::Output {
                    ops::Mul::new(self, rhs.as_expression())
                }
            }
            impl<ST, expr, __Rhs> ::std::ops::Div<__Rhs> for avg<ST, expr>
                where Self: Expression, Self: Expression,
                <Self as Expression>::SqlType: Div,
                <<Self as Expression>::SqlType as Div>::Rhs: SqlType +
                SingleValue,
                __Rhs: AsExpression<<<Self as Expression>::SqlType as
                Div>::Rhs> {
                type Output = ops::Div<Self, __Rhs::Expression>;
                fn div(self, rhs: __Rhs) -> Self::Output {
                    ops::Div::new(self, rhs.as_expression())
                }
            }
        };
    #[automatically_derived]
    impl<ST: ::core::fmt::Debug, expr: ::core::fmt::Debug> ::core::fmt::Debug
        for avg<ST, expr> {
        #[inline]
        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
            ::core::fmt::Formatter::debug_struct_field2_finish(f, "avg",
                "expr", &self.expr, "ST", &&self.ST)
        }
    }
    #[automatically_derived]
    impl<ST: ::core::clone::Clone, expr: ::core::clone::Clone>
        ::core::clone::Clone for avg<ST, expr> {
        #[inline]
        fn clone(&self) -> avg<ST, expr> {
            avg {
                expr: ::core::clone::Clone::clone(&self.expr),
                ST: ::core::clone::Clone::clone(&self.ST),
            }
        }
    }
    #[automatically_derived]
    impl<ST: ::core::marker::Copy, expr: ::core::marker::Copy>
        ::core::marker::Copy for avg<ST, expr> {
    }
    const _: () =
        {
            use diesel;
            #[allow(non_camel_case_types)]
            impl<ST: diesel::query_builder::QueryId,
                expr: diesel::query_builder::QueryId>
                diesel::query_builder::QueryId for avg<ST, expr> {
                type QueryId =
                    avg<<ST as diesel::query_builder::QueryId>::QueryId,
                    <expr as diesel::query_builder::QueryId>::QueryId>;
                const HAS_STATIC_QUERY_ID: bool =
                    <ST as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID
                            &&
                            <expr as
                                diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                        true;
                const IS_WINDOW_FUNCTION: bool =
                    <ST as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION
                            ||
                            <expr as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION
                        || false;
            }
        };
    #[doc = "The return type of [`avg()`](super::fn_name)"]
    pub type HelperType<ST, expr> =
        avg<ST, <expr as AsExpression<ST>>::Expression>;
    impl<ST: Foldable, expr> Expression for avg<ST, expr> where
        (expr): Expression {
        type SqlType = ST::Avg;
    }
    impl<ST: Foldable, expr, __DieselInternal>
        SelectableExpression<__DieselInternal> for avg<ST, expr> where
        expr: SelectableExpression<__DieselInternal>,
        Self: AppearsOnTable<__DieselInternal> {}
    impl<ST: Foldable, expr, __DieselInternal>
        AppearsOnTable<__DieselInternal> for avg<ST, expr> where
        expr: AppearsOnTable<__DieselInternal>, Self: Expression {}
    impl<ST: Foldable, expr, __DieselInternal>
        FunctionFragment<__DieselInternal> for avg<ST, expr> where
        __DieselInternal: diesel::backend::Backend,
        expr: QueryFragment<__DieselInternal> {
        const FUNCTION_NAME: &'static str = "avg";
        #[allow(unused_assignments)]
        fn walk_arguments<'__b>(&'__b self,
            mut out: AstPass<'_, '__b, __DieselInternal>) -> QueryResult<()> {
            let mut needs_comma = false;
            if !self.expr.is_noop(out.backend())? {
                if needs_comma { out.push_sql(", "); }
                self.expr.walk_ast(out.reborrow())?;
                needs_comma = true;
            }
            Ok(())
        }
    }
    impl<ST: Foldable, expr, __DieselInternal> QueryFragment<__DieselInternal>
        for avg<ST, expr> where __DieselInternal: diesel::backend::Backend,
        expr: QueryFragment<__DieselInternal> {
        fn walk_ast<'__b>(&'__b self,
            mut out: AstPass<'_, '__b, __DieselInternal>) -> QueryResult<()> {
            out.push_sql(<Self as
                    FunctionFragment<__DieselInternal>>::FUNCTION_NAME);
            out.push_sql("(");
            self.walk_arguments(out.reborrow())?;
            out.push_sql(")");
            Ok(())
        }
    }
    impl<ST: Foldable, expr, __P, __O, __F, __DieselInternal>
        WindowFunctionFragment<avg<ST, expr>, __DieselInternal> for
        OverClause<__P, __O, __F> where
        __DieselInternal: diesel::backend::Backend {}
    impl<ST: Foldable, expr> IsWindowFunction for avg<ST, expr> {
        type ArgTypes = (expr,);
    }
    impl<ST: Foldable, expr, __DieselInternal> ValidGrouping<__DieselInternal>
        for avg<ST, expr> {
        type IsAggregate = diesel::expression::is_aggregate::Yes;
    }
    impl<ST: Foldable, expr> IsAggregateFunction for avg<ST, expr> {}
}#[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}