1use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
7
8use crate::sql::{SQL, Token};
9use crate::traits::SQLParam;
10use crate::types::{ArithmeticOutput, Numeric};
11
12use super::{AggOr, AggregateKind, Expr, NullOr, Nullability, SQLExpr};
13
14#[inline]
15fn binary_op_sql<'a, V, L, R>(left: L, operator: Token, right: R) -> SQL<'a, V>
16where
17 V: SQLParam + 'a,
18 L: Expr<'a, V>,
19 R: Expr<'a, V>,
20{
21 left.into_sql()
22 .parens_if_subquery()
23 .push(operator)
24 .append(right.into_sql().parens_if_subquery())
25}
26
27impl<'a, V, T, N, A, Rhs> Add<Rhs> for SQLExpr<'a, V, T, N, A>
32where
33 V: SQLParam + 'a,
34 T: ArithmeticOutput<Rhs::SQLType>,
35 N: Nullability + NullOr<Rhs::Nullable>,
36 A: AggOr<Rhs::Aggregate>,
37 Rhs: Expr<'a, V>,
38 Rhs::SQLType: Numeric,
39 Rhs::Nullable: Nullability,
40{
41 type Output = SQLExpr<
42 'a,
43 V,
44 T::Output,
45 <N as NullOr<Rhs::Nullable>>::Output,
46 <A as AggOr<Rhs::Aggregate>>::Output,
47 >;
48
49 fn add(self, rhs: Rhs) -> Self::Output {
50 SQLExpr::new(binary_op_sql(self, Token::PLUS, rhs))
51 }
52}
53
54impl<'a, V, T, N, A, Rhs> Sub<Rhs> for SQLExpr<'a, V, T, N, A>
59where
60 V: SQLParam + 'a,
61 T: ArithmeticOutput<Rhs::SQLType>,
62 N: Nullability + NullOr<Rhs::Nullable>,
63 A: AggOr<Rhs::Aggregate>,
64 Rhs: Expr<'a, V>,
65 Rhs::SQLType: Numeric,
66 Rhs::Nullable: Nullability,
67{
68 type Output = SQLExpr<
69 'a,
70 V,
71 T::Output,
72 <N as NullOr<Rhs::Nullable>>::Output,
73 <A as AggOr<Rhs::Aggregate>>::Output,
74 >;
75
76 fn sub(self, rhs: Rhs) -> Self::Output {
77 SQLExpr::new(binary_op_sql(self, Token::MINUS, rhs))
78 }
79}
80
81impl<'a, V, T, N, A, Rhs> Mul<Rhs> for SQLExpr<'a, V, T, N, A>
86where
87 V: SQLParam + 'a,
88 T: ArithmeticOutput<Rhs::SQLType>,
89 N: Nullability + NullOr<Rhs::Nullable>,
90 A: AggOr<Rhs::Aggregate>,
91 Rhs: Expr<'a, V>,
92 Rhs::SQLType: Numeric,
93 Rhs::Nullable: Nullability,
94{
95 type Output = SQLExpr<
96 'a,
97 V,
98 T::Output,
99 <N as NullOr<Rhs::Nullable>>::Output,
100 <A as AggOr<Rhs::Aggregate>>::Output,
101 >;
102
103 fn mul(self, rhs: Rhs) -> Self::Output {
104 SQLExpr::new(binary_op_sql(self, Token::STAR, rhs))
105 }
106}
107
108impl<'a, V, T, N, A, Rhs> Div<Rhs> for SQLExpr<'a, V, T, N, A>
113where
114 V: SQLParam + 'a,
115 T: ArithmeticOutput<Rhs::SQLType>,
116 N: Nullability + NullOr<Rhs::Nullable>,
117 A: AggOr<Rhs::Aggregate>,
118 Rhs: Expr<'a, V>,
119 Rhs::SQLType: Numeric,
120 Rhs::Nullable: Nullability,
121{
122 type Output = SQLExpr<
123 'a,
124 V,
125 T::Output,
126 <N as NullOr<Rhs::Nullable>>::Output,
127 <A as AggOr<Rhs::Aggregate>>::Output,
128 >;
129
130 fn div(self, rhs: Rhs) -> Self::Output {
131 SQLExpr::new(binary_op_sql(self, Token::SLASH, rhs))
132 }
133}
134
135impl<'a, V, T, N, A, Rhs> Rem<Rhs> for SQLExpr<'a, V, T, N, A>
140where
141 V: SQLParam + 'a,
142 T: ArithmeticOutput<Rhs::SQLType>,
143 N: Nullability + NullOr<Rhs::Nullable>,
144 A: AggOr<Rhs::Aggregate>,
145 Rhs: Expr<'a, V>,
146 Rhs::SQLType: Numeric,
147 Rhs::Nullable: Nullability,
148{
149 type Output = SQLExpr<
150 'a,
151 V,
152 T::Output,
153 <N as NullOr<Rhs::Nullable>>::Output,
154 <A as AggOr<Rhs::Aggregate>>::Output,
155 >;
156
157 fn rem(self, rhs: Rhs) -> Self::Output {
158 SQLExpr::new(binary_op_sql(self, Token::REM, rhs))
159 }
160}
161
162impl<'a, V, T, N, A> Neg for SQLExpr<'a, V, T, N, A>
167where
168 V: SQLParam + 'a,
169 T: Numeric,
170 N: Nullability,
171 A: AggregateKind,
172{
173 type Output = Self;
174
175 fn neg(self) -> Self::Output {
176 SQLExpr::new(SQL::from(Token::MINUS).append(self.into_sql().parens()))
177 }
178}