use std::{collections::HashMap, fmt::Display};
use crate::{catalog::TableSchema, value::Value};
#[derive(Debug, Clone)]
pub enum Statement {
CreateTable(TableSchema),
DropTable(String),
Insert(InsertStatement),
Update(UpdateStatement),
Select(SelectStatement),
Delete(DeleteStatement),
}
#[derive(Debug, Clone)]
pub struct SelectStatement {
pub explain: bool,
pub expr: Vec<Expr>,
pub cond: Option<Expr>,
pub table_mappings: Vec<(String, String)>,
pub version: Option<u64>,
}
#[derive(Debug, Clone)]
pub struct DeleteStatement {
pub table: String,
pub cond: Option<Expr>,
}
#[derive(Debug, Clone)]
pub struct InsertStatement {
pub table: String,
pub values: HashMap<String, Expr>,
}
#[derive(Debug, Clone)]
pub struct UpdateStatement {
pub table: String,
pub sets: Vec<Set>,
pub cond: Option<Expr>,
}
#[derive(Debug, Clone)]
pub struct Set {
pub lhs: Column,
pub rhs: Expr,
}
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum BinOp {
Eq,
NEq,
Gt,
GtEq,
Lt,
LtEq,
Add,
Sub,
Mul,
Div,
Mod,
And,
Or,
}
impl BinOp {
pub fn precedence(self) -> usize {
match self {
BinOp::Mul | BinOp::Div | BinOp::Mod => 3,
BinOp::Add | BinOp::Sub => 4,
BinOp::Gt | BinOp::GtEq | BinOp::Lt | BinOp::LtEq => 6,
BinOp::Eq | BinOp::NEq => 7,
BinOp::And => 11,
BinOp::Or => 12,
}
}
}
impl Display for BinOp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::Eq => "=",
Self::NEq => "!=",
Self::Gt => ">",
Self::GtEq => ">=",
Self::Lt => "<",
Self::LtEq => "<=",
Self::And => "AND",
Self::Or => "OR",
Self::Add => "+",
Self::Sub => "-",
Self::Mul => "*",
Self::Div => "/",
Self::Mod => "%",
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum UnOp {
Not,
}
impl Display for UnOp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
UnOp::Not => "NOT",
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Expr {
Literal(Value),
Binding(u64),
Unary(UnOp, Box<Expr>),
Bin(Box<Expr>, BinOp, Box<Expr>),
Column(Column),
Edge(Vec<Expr>, (String, String), Option<Vec<Expr>>, Box<Expr>),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Column(pub String, pub String);
impl Display for Column {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}.{}", self.0, self.1)
}
}
impl Display for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Binding(b) => write!(f, "?{b}"),
Self::Literal(v) => write!(f, "{v}"),
Self::Unary(op, rhs) => {
write!(f, "({op} {rhs})",)
}
Self::Bin(lhs, op, rhs) => {
write!(f, "({lhs} {op} {rhs})",)
}
Self::Column(col) => col.fmt(f),
Self::Edge(lhs, mapping, rhs, e) => {
write!(
f,
"({})->{} {}->{e}",
lhs.iter()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join(","),
format!("{} AS {}", mapping.0, mapping.1),
if let Some(rhs) = rhs {
format!(
"({})",
rhs.iter()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join(",")
)
} else {
"".to_string()
}
)
}
}
}
}