diesel/sql_types/ops.rs
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!`](../../macro.numeric_expr.html).
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.
33
34use super::*;
35
36/// Represents SQL types which can be added.
37pub trait Add {
38 /// The SQL type which can be added to this one
39 type Rhs;
40 /// The SQL type of the result of adding `Rhs` to `Self`
41 type Output;
42}
43
44/// Represents SQL types which can be subtracted.
45pub trait Sub {
46 /// The SQL type which can be subtracted from this one
47 type Rhs;
48 /// The SQL type of the result of subtracting `Rhs` from `Self`
49 type Output;
50}
51
52/// Represents SQL types which can be multiplied.
53pub trait Mul {
54 /// The SQL type which this can be multiplied by
55 type Rhs;
56 /// The SQL type of the result of multiplying `Self` by `Rhs`
57 type Output;
58}
59
60/// Represents SQL types which can be divided.
61pub trait Div {
62 /// The SQL type which this one can be divided by
63 type Rhs;
64 /// The SQL type of the result of dividing `Self` by `Rhs`
65 type Output;
66}
67
68macro_rules! numeric_type {
69 ($($tpe: ident),*) => {
70 $(
71 impl Add for $tpe {
72 type Rhs = $tpe;
73 type Output = $tpe;
74 }
75
76 impl Sub for $tpe {
77 type Rhs = $tpe;
78 type Output = $tpe;
79 }
80
81 impl Mul for $tpe {
82 type Rhs = $tpe;
83 type Output = $tpe;
84 }
85
86 impl Div for $tpe {
87 type Rhs = $tpe;
88 type Output = $tpe;
89 }
90 )*
91 }
92}
93
94numeric_type!(SmallInt, Integer, BigInt, Float, Double, Numeric);
95
96impl Add for Time {
97 type Rhs = Interval;
98 type Output = Time;
99}
100
101impl Sub for Time {
102 type Rhs = Interval;
103 type Output = Time;
104}
105
106impl Add for Date {
107 type Rhs = Interval;
108 type Output = Timestamp;
109}
110
111impl Sub for Date {
112 type Rhs = Interval;
113 type Output = Timestamp;
114}
115
116impl Add for Timestamp {
117 type Rhs = Interval;
118 type Output = Timestamp;
119}
120
121impl Sub for Timestamp {
122 type Rhs = Interval;
123 type Output = Timestamp;
124}
125
126impl Add for Interval {
127 type Rhs = Interval;
128 type Output = Interval;
129}
130
131impl Sub for Interval {
132 type Rhs = Interval;
133 type Output = Interval;
134}
135
136impl Mul for Interval {
137 type Rhs = Integer;
138 type Output = Interval;
139}
140
141impl Div for Interval {
142 type Rhs = Integer;
143 type Output = Interval;
144}
145
146impl<T> Add for Nullable<T>
147where
148 T: Add + NotNull,
149 T::Rhs: NotNull,
150 T::Output: NotNull,
151{
152 type Rhs = Nullable<T::Rhs>;
153 type Output = Nullable<T::Output>;
154}
155
156impl<T> Sub for Nullable<T>
157where
158 T: Sub + NotNull,
159 T::Rhs: NotNull,
160 T::Output: NotNull,
161{
162 type Rhs = Nullable<T::Rhs>;
163 type Output = Nullable<T::Output>;
164}
165
166impl<T> Mul for Nullable<T>
167where
168 T: Mul + NotNull,
169 T::Rhs: NotNull,
170 T::Output: NotNull,
171{
172 type Rhs = Nullable<T::Rhs>;
173 type Output = Nullable<T::Output>;
174}
175
176impl<T> Div for Nullable<T>
177where
178 T: Div + NotNull,
179 T::Rhs: NotNull,
180 T::Output: NotNull,
181{
182 type Rhs = Nullable<T::Rhs>;
183 type Output = Nullable<T::Output>;
184}