drizzle_core/expr/
column_ops.rs1use core::marker::PhantomData;
7
8use crate::sql::{SQL, Token};
9use crate::traits::{SQLParam, ToSQL};
10use crate::types::{ArithmeticOutput, Numeric};
11
12use super::{Expr, NullOr, Nullability, Scalar};
13
14#[derive(Debug, Clone, Copy)]
18pub struct ColumnBinOp<Lhs, Rhs, Op> {
19 lhs: Lhs,
20 rhs: Rhs,
21 _op: PhantomData<Op>,
22}
23
24impl<Lhs, Rhs, Op> ColumnBinOp<Lhs, Rhs, Op> {
25 #[inline]
26 pub fn new(lhs: Lhs, rhs: Rhs) -> Self {
27 Self {
28 lhs,
29 rhs,
30 _op: PhantomData,
31 }
32 }
33}
34
35#[derive(Debug, Clone, Copy)]
37pub struct OpAdd;
38
39#[derive(Debug, Clone, Copy)]
41pub struct OpSub;
42
43#[derive(Debug, Clone, Copy)]
45pub struct OpMul;
46
47#[derive(Debug, Clone, Copy)]
49pub struct OpDiv;
50
51#[derive(Debug, Clone, Copy)]
53pub struct OpRem;
54
55pub trait BinOpToken {
57 const TOKEN: Token;
58}
59
60impl BinOpToken for OpAdd {
61 const TOKEN: Token = Token::PLUS;
62}
63
64impl BinOpToken for OpSub {
65 const TOKEN: Token = Token::MINUS;
66}
67
68impl BinOpToken for OpMul {
69 const TOKEN: Token = Token::STAR;
70}
71
72impl BinOpToken for OpDiv {
73 const TOKEN: Token = Token::SLASH;
74}
75
76impl BinOpToken for OpRem {
77 const TOKEN: Token = Token::REM;
78}
79
80impl<'a, V, Lhs, Rhs, Op> ToSQL<'a, V> for ColumnBinOp<Lhs, Rhs, Op>
81where
82 V: SQLParam,
83 Lhs: ToSQL<'a, V>,
84 Rhs: ToSQL<'a, V>,
85 Op: BinOpToken,
86{
87 fn to_sql(&self) -> SQL<'a, V> {
88 self.lhs.to_sql().push(Op::TOKEN).append(self.rhs.to_sql())
89 }
90}
91
92impl<'a, V, Lhs, Rhs, Op> Expr<'a, V> for ColumnBinOp<Lhs, Rhs, Op>
93where
94 V: SQLParam,
95 Lhs: Expr<'a, V>,
96 Rhs: Expr<'a, V>,
97 Lhs::SQLType: Numeric + ArithmeticOutput<Rhs::SQLType>,
98 Rhs::SQLType: Numeric,
99 Lhs::Nullable: NullOr<Rhs::Nullable>,
100 Rhs::Nullable: Nullability,
101 Op: BinOpToken,
102{
103 type SQLType = <Lhs::SQLType as ArithmeticOutput<Rhs::SQLType>>::Output;
104 type Nullable = <Lhs::Nullable as NullOr<Rhs::Nullable>>::Output;
105 type Aggregate = Scalar;
106}
107
108#[derive(Debug, Clone, Copy)]
110pub struct ColumnNeg<T> {
111 inner: T,
112}
113
114impl<T> ColumnNeg<T> {
115 #[inline]
116 pub fn new(inner: T) -> Self {
117 Self { inner }
118 }
119}
120
121impl<'a, V, T> ToSQL<'a, V> for ColumnNeg<T>
122where
123 V: SQLParam,
124 T: ToSQL<'a, V>,
125{
126 fn to_sql(&self) -> SQL<'a, V> {
127 SQL::raw("-").append(self.inner.to_sql())
128 }
129}
130
131impl<'a, V, T> Expr<'a, V> for ColumnNeg<T>
132where
133 V: SQLParam,
134 T: Expr<'a, V>,
135 T::SQLType: Numeric,
136{
137 type SQLType = T::SQLType;
138 type Nullable = T::Nullable;
139 type Aggregate = Scalar;
140}