use crate::{posql_time::PoSQLTimestamp, Identifier};
use alloc::{boxed::Box, string::String, vec::Vec};
use bigdecimal::BigDecimal;
use core::{
fmt,
fmt::{Display, Formatter},
hash::Hash,
};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum SetExpression {
Query {
result_exprs: Vec<SelectResultExpr>,
from: Vec<Box<TableExpression>>,
where_expr: Option<Box<Expression>>,
group_by: Vec<Identifier>,
},
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum SelectResultExpr {
ALL,
AliasedResultExpr(AliasedResultExpr),
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct AliasedResultExpr {
pub expr: Box<Expression>,
pub alias: Identifier,
}
impl From<AliasedResultExpr> for SelectResultExpr {
fn from(value: AliasedResultExpr) -> Self {
SelectResultExpr::AliasedResultExpr(AliasedResultExpr {
expr: value.expr,
alias: value.alias,
})
}
}
impl AliasedResultExpr {
#[must_use]
pub fn new(expr: Expression, alias: Identifier) -> Self {
Self {
expr: Box::new(expr),
alias,
}
}
#[must_use]
pub fn try_as_identifier(&self) -> Option<&Identifier> {
match self.expr.as_ref() {
Expression::Column(column) => Some(column),
_ => None,
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum TableExpression {
Named {
table: Identifier,
schema: Option<Identifier>,
},
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum BinaryOperator {
Add,
Subtract,
Multiply,
Division,
And,
Or,
Equal,
LessThan,
GreaterThan,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum UnaryOperator {
Not,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum AggregationOperator {
Max,
Min,
Sum,
Count,
First,
}
impl Display for AggregationOperator {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
AggregationOperator::Max => write!(f, "max"),
AggregationOperator::Min => write!(f, "min"),
AggregationOperator::Sum => write!(f, "sum"),
AggregationOperator::Count => write!(f, "count"),
AggregationOperator::First => write!(f, "first"),
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Hash)]
pub enum Expression {
Literal(Literal),
Column(Identifier),
Unary {
op: UnaryOperator,
expr: Box<Expression>,
},
Binary {
op: BinaryOperator,
left: Box<Expression>,
right: Box<Expression>,
},
Wildcard,
Aggregation {
op: AggregationOperator,
expr: Box<Expression>,
},
}
impl Expression {
#[must_use]
pub fn sum(self) -> Box<Self> {
Box::new(Expression::Aggregation {
op: AggregationOperator::Sum,
expr: Box::new(self),
})
}
#[must_use]
pub fn max(self) -> Box<Self> {
Box::new(Expression::Aggregation {
op: AggregationOperator::Max,
expr: Box::new(self),
})
}
#[must_use]
pub fn min(self) -> Box<Self> {
Box::new(Expression::Aggregation {
op: AggregationOperator::Min,
expr: Box::new(self),
})
}
#[must_use]
pub fn count(self) -> Box<Self> {
Box::new(Expression::Aggregation {
op: AggregationOperator::Count,
expr: Box::new(self),
})
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[must_use]
pub fn first(self) -> Box<Self> {
Box::new(Expression::Aggregation {
op: AggregationOperator::First,
expr: Box::new(self),
})
}
#[must_use]
pub fn alias(self, alias: &str) -> AliasedResultExpr {
AliasedResultExpr {
expr: Box::new(self),
alias: alias.parse().unwrap(),
}
}
}
impl core::ops::Add<Box<Expression>> for Box<Expression> {
type Output = Box<Expression>;
fn add(self, rhs: Box<Expression>) -> Box<Expression> {
Box::new(Expression::Binary {
op: BinaryOperator::Add,
left: self,
right: rhs,
})
}
}
impl core::ops::Mul<Box<Expression>> for Box<Expression> {
type Output = Box<Expression>;
fn mul(self, rhs: Box<Expression>) -> Box<Expression> {
Box::new(Expression::Binary {
op: BinaryOperator::Multiply,
left: self,
right: rhs,
})
}
}
impl core::ops::Div<Box<Expression>> for Box<Expression> {
type Output = Box<Expression>;
fn div(self, rhs: Box<Expression>) -> Box<Expression> {
Box::new(Expression::Binary {
op: BinaryOperator::Division,
left: self,
right: rhs,
})
}
}
impl core::ops::Sub<Box<Expression>> for Box<Expression> {
type Output = Box<Expression>;
fn sub(self, rhs: Box<Expression>) -> Box<Expression> {
Box::new(Expression::Binary {
op: BinaryOperator::Subtract,
left: self,
right: rhs,
})
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct OrderBy {
pub expr: Identifier,
pub direction: OrderByDirection,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
pub enum OrderByDirection {
Asc,
Desc,
}
impl Display for OrderByDirection {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
OrderByDirection::Asc => write!(f, "asc"),
OrderByDirection::Desc => write!(f, "desc"),
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Slice {
pub number_rows: u64,
pub offset_value: i64,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Hash)]
pub enum Literal {
Boolean(bool),
BigInt(i64),
Int128(i128),
VarChar(String),
VarBinary(Vec<u8>),
Decimal(BigDecimal),
Timestamp(PoSQLTimestamp),
}
impl From<bool> for Literal {
fn from(val: bool) -> Self {
Literal::Boolean(val)
}
}
macro_rules! impl_int_to_literal {
($tt:ty) => {
impl From<$tt> for Literal {
fn from(val: $tt) -> Self {
Literal::BigInt(i64::from(val))
}
}
};
}
impl_int_to_literal!(i8);
impl_int_to_literal!(u8);
impl_int_to_literal!(i16);
impl_int_to_literal!(u16);
impl_int_to_literal!(i32);
impl_int_to_literal!(u32);
impl_int_to_literal!(i64);
impl From<i128> for Literal {
fn from(val: i128) -> Self {
Literal::Int128(val)
}
}
macro_rules! impl_string_to_literal {
($tt:ty) => {
impl From<$tt> for Literal {
fn from(val: $tt) -> Self {
Literal::VarChar(val.into())
}
}
};
}
impl_string_to_literal!(&str);
impl_string_to_literal!(String);
impl From<BigDecimal> for Literal {
fn from(val: BigDecimal) -> Self {
Literal::Decimal(val)
}
}
impl From<PoSQLTimestamp> for Literal {
fn from(time: PoSQLTimestamp) -> Self {
Literal::Timestamp(time)
}
}
pub(crate) fn append<T>(list: Vec<T>, item: T) -> Vec<T> {
let mut result = list;
result.push(item);
result
}