use core::marker::PhantomData;
use crate::sql::{SQL, Token};
use crate::traits::{SQLParam, ToSQL};
use crate::types::{ArithmeticOutput, Numeric};
use super::{AggOr, AggregateKind, Expr, NullOr, Nullability};
#[derive(Debug, Clone, Copy)]
pub struct ColumnBinOp<Lhs, Rhs, Op> {
lhs: Lhs,
rhs: Rhs,
_op: PhantomData<Op>,
}
impl<Lhs, Rhs, Op> ColumnBinOp<Lhs, Rhs, Op> {
#[inline]
pub const fn new(lhs: Lhs, rhs: Rhs) -> Self {
Self {
lhs,
rhs,
_op: PhantomData,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct OpAdd;
#[derive(Debug, Clone, Copy)]
pub struct OpSub;
#[derive(Debug, Clone, Copy)]
pub struct OpMul;
#[derive(Debug, Clone, Copy)]
pub struct OpDiv;
#[derive(Debug, Clone, Copy)]
pub struct OpRem;
pub trait BinOpToken {
const TOKEN: Token;
}
impl BinOpToken for OpAdd {
const TOKEN: Token = Token::PLUS;
}
impl BinOpToken for OpSub {
const TOKEN: Token = Token::MINUS;
}
impl BinOpToken for OpMul {
const TOKEN: Token = Token::STAR;
}
impl BinOpToken for OpDiv {
const TOKEN: Token = Token::SLASH;
}
impl BinOpToken for OpRem {
const TOKEN: Token = Token::REM;
}
impl<'a, V, Lhs, Rhs, Op> ToSQL<'a, V> for ColumnBinOp<Lhs, Rhs, Op>
where
V: SQLParam,
Lhs: ToSQL<'a, V>,
Rhs: ToSQL<'a, V>,
Op: BinOpToken,
{
fn to_sql(&self) -> SQL<'a, V> {
self.lhs.to_sql().push(Op::TOKEN).append(self.rhs.to_sql())
}
}
impl<'a, V, Lhs, Rhs, Op> Expr<'a, V> for ColumnBinOp<Lhs, Rhs, Op>
where
V: SQLParam,
Lhs: Expr<'a, V>,
Rhs: Expr<'a, V>,
Lhs::SQLType: Numeric + ArithmeticOutput<Rhs::SQLType>,
Rhs::SQLType: Numeric,
Lhs::Nullable: NullOr<Rhs::Nullable>,
Rhs::Nullable: Nullability,
Lhs::Aggregate: AggOr<Rhs::Aggregate>,
Rhs::Aggregate: AggregateKind,
Op: BinOpToken,
{
type SQLType = <Lhs::SQLType as ArithmeticOutput<Rhs::SQLType>>::Output;
type Nullable = <Lhs::Nullable as NullOr<Rhs::Nullable>>::Output;
type Aggregate = <Lhs::Aggregate as AggOr<Rhs::Aggregate>>::Output;
}
impl<Lhs: super::HasAggStatus, Rhs, Op> super::HasAggStatus for ColumnBinOp<Lhs, Rhs, Op> {
type Status = Lhs::Status;
}
impl<Lhs, Rhs, Op> crate::row::ExprValueType for ColumnBinOp<Lhs, Rhs, Op>
where
Lhs: crate::row::ExprValueType,
{
type ValueType = Lhs::ValueType;
}
impl<Lhs, Rhs, Op> crate::row::IntoSelectTarget for ColumnBinOp<Lhs, Rhs, Op> {
type Marker = crate::row::SelectCols<(Self,)>;
}
#[derive(Debug, Clone, Copy)]
pub struct ColumnNeg<T> {
inner: T,
}
impl<T> ColumnNeg<T> {
#[inline]
pub const fn new(inner: T) -> Self {
Self { inner }
}
}
impl<'a, V, T> ToSQL<'a, V> for ColumnNeg<T>
where
V: SQLParam,
T: ToSQL<'a, V>,
{
fn to_sql(&self) -> SQL<'a, V> {
SQL::raw("-").append(self.inner.to_sql())
}
}
impl<'a, V, T> Expr<'a, V> for ColumnNeg<T>
where
V: SQLParam,
T: Expr<'a, V>,
T::SQLType: Numeric,
{
type SQLType = T::SQLType;
type Nullable = T::Nullable;
type Aggregate = T::Aggregate;
}
impl<T: super::HasAggStatus> super::HasAggStatus for ColumnNeg<T> {
type Status = T::Status;
}
impl<T: crate::row::ExprValueType> crate::row::ExprValueType for ColumnNeg<T> {
type ValueType = T::ValueType;
}
impl<T> crate::row::IntoSelectTarget for ColumnNeg<T> {
type Marker = crate::row::SelectCols<(Self,)>;
}