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_expr_sql()
22        .push(operator)
23        .append(right.into_expr_sql())
24}
25
26// =============================================================================
27// Addition
28// =============================================================================
29
30impl<'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
53// =============================================================================
54// Subtraction
55// =============================================================================
56
57impl<'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
80// =============================================================================
81// Multiplication
82// =============================================================================
83
84impl<'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
107// =============================================================================
108// Division
109// =============================================================================
110
111impl<'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
134// =============================================================================
135// Remainder (Modulo)
136// =============================================================================
137
138impl<'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
161// =============================================================================
162// Negation
163// =============================================================================
164
165impl<'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}