Skip to main content

drizzle_core/expr/
ops.rs

1//! Arithmetic operations using `std::ops` traits.
2//!
3//! This module implements `Add`, `Sub`, `Mul`, `Div`, `Rem` for `SQLExpr`,
4//! enabling natural Rust syntax for SQL arithmetic.
5
6use 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
27// =============================================================================
28// Addition
29// =============================================================================
30
31impl<'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
54// =============================================================================
55// Subtraction
56// =============================================================================
57
58impl<'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
81// =============================================================================
82// Multiplication
83// =============================================================================
84
85impl<'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
108// =============================================================================
109// Division
110// =============================================================================
111
112impl<'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
135// =============================================================================
136// Remainder (Modulo)
137// =============================================================================
138
139impl<'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
162// =============================================================================
163// Negation
164// =============================================================================
165
166impl<'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}