1//! Represents the output of numeric operators in SQL
2//!
3//! Apps should not need to concern themselves with this module.
4//! If you are looking for where the actual implementation of `std::ops::Add`
5//! and friends are generated for columns, see
6//! [`numeric_expr!`](super::super::numeric_expr!).
7//!
8//! Crates which add new types which allow numeric operators should implement
9//! these traits to specify what the output is for a given right hand side.
10//!
11//! Unlike the traits in `std::ops`, the right hand side is an associated type
12//! rather than a type parameter. The biggest drawback of this is that any type
13//! can only have one right hand type which can be added/subtracted, etc. The
14//! most immediately noticeable effect of this is that you cannot add a nullable
15//! number to one that is not nullable.
16//!
17//! The reason for this is because of the impl of `std::ops::Add` that we need
18//! to be able to write. We want the right hand side to allow Rust values which
19//! should be sent as bind parameters, not just other Diesel expressions. That
20//! means the impl would look like this:
21//!
22//! ```ignore
23//! impl<ST, T> std::ops::Add<T> for my_column
24//! where
25//! T: AsExpression<ST>,
26//! my_column::SqlType: diesel::ops::Add<ST>,
27//! ```
28//!
29//! This impl is not valid in Rust, as `ST` is not constrained by the trait or
30//! the implementing type. If there were two valid types for `ST` which
31//! satisfied all constraints, Rust would not know which one to use, and there
32//! would be no way for the user to specify which one should be used.
3334use super::*;
3536/// Represents SQL types which can be added.
37pub trait Add {
38/// The SQL type which can be added to this one
39type Rhs: SqlType;
40/// The SQL type of the result of adding `Rhs` to `Self`
41type Output: SqlType;
42}
4344/// Represents SQL types which can be subtracted.
45pub trait Sub {
46/// The SQL type which can be subtracted from this one
47type Rhs: SqlType;
48/// The SQL type of the result of subtracting `Rhs` from `Self`
49type Output: SqlType;
50}
5152/// Represents SQL types which can be multiplied.
53pub trait Mul {
54/// The SQL type which this can be multiplied by
55type Rhs: SqlType;
56/// The SQL type of the result of multiplying `Self` by `Rhs`
57type Output: SqlType;
58}
5960/// Represents SQL types which can be divided.
61pub trait Div {
62/// The SQL type which this one can be divided by
63type Rhs: SqlType;
64/// The SQL type of the result of dividing `Self` by `Rhs`
65type Output: SqlType;
66}
6768macro_rules! numeric_type {
69 ($($tpe: ident),*) => {
70 $(
71impl Add for $tpe {
72type Rhs = $tpe;
73type Output = $tpe;
74 }
7576impl Sub for $tpe {
77type Rhs = $tpe;
78type Output = $tpe;
79 }
8081impl Mul for $tpe {
82type Rhs = $tpe;
83type Output = $tpe;
84 }
8586impl Div for $tpe {
87type Rhs = $tpe;
88type Output = $tpe;
89 }
90 )*
91 }
92}
9394numeric_type!(SmallInt, Integer, BigInt, Float, Double, Numeric);
9596impl Add for Time {
97type Rhs = Interval;
98type Output = Time;
99}
100101impl Sub for Time {
102type Rhs = Interval;
103type Output = Time;
104}
105106impl Add for Date {
107type Rhs = Interval;
108type Output = Timestamp;
109}
110111impl Sub for Date {
112type Rhs = Interval;
113type Output = Timestamp;
114}
115116impl Add for Timestamp {
117type Rhs = Interval;
118type Output = Timestamp;
119}
120121impl Sub for Timestamp {
122type Rhs = Interval;
123type Output = Timestamp;
124}
125126impl Add for Interval {
127type Rhs = Interval;
128type Output = Interval;
129}
130131impl Sub for Interval {
132type Rhs = Interval;
133type Output = Interval;
134}
135136impl Mul for Interval {
137type Rhs = Integer;
138type Output = Interval;
139}
140141impl Div for Interval {
142type Rhs = Integer;
143type Output = Interval;
144}
145146impl<T> Add for Nullable<T>
147where
148T: Add + SqlType<IsNull = is_nullable::NotNull>,
149 T::Rhs: SqlType<IsNull = is_nullable::NotNull>,
150 T::Output: SqlType<IsNull = is_nullable::NotNull>,
151{
152type Rhs = Nullable<T::Rhs>;
153type Output = Nullable<T::Output>;
154}
155156impl<T> Sub for Nullable<T>
157where
158T: Sub + SqlType<IsNull = is_nullable::NotNull>,
159 T::Rhs: SqlType<IsNull = is_nullable::NotNull>,
160 T::Output: SqlType<IsNull = is_nullable::NotNull>,
161{
162type Rhs = Nullable<T::Rhs>;
163type Output = Nullable<T::Output>;
164}
165166impl<T> Mul for Nullable<T>
167where
168T: Mul + SqlType<IsNull = is_nullable::NotNull>,
169 T::Rhs: SqlType<IsNull = is_nullable::NotNull>,
170 T::Output: SqlType<IsNull = is_nullable::NotNull>,
171{
172type Rhs = Nullable<T::Rhs>;
173type Output = Nullable<T::Output>;
174}
175176impl<T> Div for Nullable<T>
177where
178T: Div + SqlType<IsNull = is_nullable::NotNull>,
179 T::Rhs: SqlType<IsNull = is_nullable::NotNull>,
180 T::Output: SqlType<IsNull = is_nullable::NotNull>,
181{
182type Rhs = Nullable<T::Rhs>;
183type Output = Nullable<T::Output>;
184}