1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use sql_types::{self, NotNull};

/// Represents SQL types which can be used with `SUM` and `AVG`
pub trait Foldable {
    /// The SQL type of `sum(this_type)`
    type Sum;
    /// The SQL type of `avg(this_type)`
    type Avg;
}

impl<T> Foldable for sql_types::Nullable<T>
where
    T: Foldable + NotNull,
{
    type Sum = T::Sum;
    type Avg = T::Avg;
}

macro_rules! foldable_impls {
    ($($Source:ty => ($SumType:ty, $AvgType:ty)),+,) => {
        $(
            impl Foldable for $Source {
                type Sum = sql_types::Nullable<$SumType>;
                type Avg = sql_types::Nullable<$AvgType>;
            }
        )+
    }
}

foldable_impls! {
    sql_types::SmallInt => (sql_types::BigInt, sql_types::Numeric),
    sql_types::Integer => (sql_types::BigInt, sql_types::Numeric),
    sql_types::BigInt => (sql_types::Numeric, sql_types::Numeric),

    sql_types::Float => (sql_types::Float, sql_types::Double),
    sql_types::Double => (sql_types::Double, sql_types::Double),
    sql_types::Numeric => (sql_types::Numeric, sql_types::Numeric),

    sql_types::Interval => (sql_types::Interval, sql_types::Interval),
}

#[cfg(feature = "mysql")]
foldable_impls! {
    sql_types::Unsigned<sql_types::SmallInt> => (sql_types::Unsigned<sql_types::BigInt>, sql_types::Numeric),
    sql_types::Unsigned<sql_types::Integer> => (sql_types::Unsigned<sql_types::BigInt>, sql_types::Numeric),
    sql_types::Unsigned<sql_types::BigInt> => (sql_types::Numeric, sql_types::Numeric),
}