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_expr_sql()
22 .push(operator)
23 .append(right.into_expr_sql())
24}
25
26impl<'a, V, T, N, A, Rhs> Add<Rhs> for SQLExpr<'a, V, T, N, A>
31where
32 V: SQLParam + 'a,
33 T: ArithmeticOutput<Rhs::SQLType>,
34 N: Nullability + NullOr<Rhs::Nullable>,
35 A: AggOr<Rhs::Aggregate>,
36 Rhs: Expr<'a, V>,
37 Rhs::SQLType: Numeric,
38 Rhs::Nullable: Nullability,
39{
40 type Output = SQLExpr<
41 'a,
42 V,
43 T::Output,
44 <N as NullOr<Rhs::Nullable>>::Output,
45 <A as AggOr<Rhs::Aggregate>>::Output,
46 >;
47
48 fn add(self, rhs: Rhs) -> Self::Output {
49 SQLExpr::new(binary_op_sql(self, Token::PLUS, rhs))
50 }
51}
52
53impl<'a, V, T, N, A, Rhs> Sub<Rhs> for SQLExpr<'a, V, T, N, A>
58where
59 V: SQLParam + 'a,
60 T: ArithmeticOutput<Rhs::SQLType>,
61 N: Nullability + NullOr<Rhs::Nullable>,
62 A: AggOr<Rhs::Aggregate>,
63 Rhs: Expr<'a, V>,
64 Rhs::SQLType: Numeric,
65 Rhs::Nullable: Nullability,
66{
67 type Output = SQLExpr<
68 'a,
69 V,
70 T::Output,
71 <N as NullOr<Rhs::Nullable>>::Output,
72 <A as AggOr<Rhs::Aggregate>>::Output,
73 >;
74
75 fn sub(self, rhs: Rhs) -> Self::Output {
76 SQLExpr::new(binary_op_sql(self, Token::MINUS, rhs))
77 }
78}
79
80impl<'a, V, T, N, A, Rhs> Mul<Rhs> for SQLExpr<'a, V, T, N, A>
85where
86 V: SQLParam + 'a,
87 T: ArithmeticOutput<Rhs::SQLType>,
88 N: Nullability + NullOr<Rhs::Nullable>,
89 A: AggOr<Rhs::Aggregate>,
90 Rhs: Expr<'a, V>,
91 Rhs::SQLType: Numeric,
92 Rhs::Nullable: Nullability,
93{
94 type Output = SQLExpr<
95 'a,
96 V,
97 T::Output,
98 <N as NullOr<Rhs::Nullable>>::Output,
99 <A as AggOr<Rhs::Aggregate>>::Output,
100 >;
101
102 fn mul(self, rhs: Rhs) -> Self::Output {
103 SQLExpr::new(binary_op_sql(self, Token::STAR, rhs))
104 }
105}
106
107impl<'a, V, T, N, A, Rhs> Div<Rhs> for SQLExpr<'a, V, T, N, A>
112where
113 V: SQLParam + 'a,
114 T: ArithmeticOutput<Rhs::SQLType>,
115 N: Nullability + NullOr<Rhs::Nullable>,
116 A: AggOr<Rhs::Aggregate>,
117 Rhs: Expr<'a, V>,
118 Rhs::SQLType: Numeric,
119 Rhs::Nullable: Nullability,
120{
121 type Output = SQLExpr<
122 'a,
123 V,
124 T::Output,
125 <N as NullOr<Rhs::Nullable>>::Output,
126 <A as AggOr<Rhs::Aggregate>>::Output,
127 >;
128
129 fn div(self, rhs: Rhs) -> Self::Output {
130 SQLExpr::new(binary_op_sql(self, Token::SLASH, rhs))
131 }
132}
133
134impl<'a, V, T, N, A, Rhs> Rem<Rhs> for SQLExpr<'a, V, T, N, A>
139where
140 V: SQLParam + 'a,
141 T: ArithmeticOutput<Rhs::SQLType>,
142 N: Nullability + NullOr<Rhs::Nullable>,
143 A: AggOr<Rhs::Aggregate>,
144 Rhs: Expr<'a, V>,
145 Rhs::SQLType: Numeric,
146 Rhs::Nullable: Nullability,
147{
148 type Output = SQLExpr<
149 'a,
150 V,
151 T::Output,
152 <N as NullOr<Rhs::Nullable>>::Output,
153 <A as AggOr<Rhs::Aggregate>>::Output,
154 >;
155
156 fn rem(self, rhs: Rhs) -> Self::Output {
157 SQLExpr::new(binary_op_sql(self, Token::REM, rhs))
158 }
159}
160
161impl<'a, V, T, N, A> Neg for SQLExpr<'a, V, T, N, A>
166where
167 V: SQLParam + 'a,
168 T: Numeric,
169 N: Nullability,
170 A: AggregateKind,
171{
172 type Output = Self;
173
174 fn neg(self) -> Self::Output {
175 SQLExpr::new(SQL::from(Token::MINUS).append(self.into_expr_sql().parens()))
176 }
177}