matdb 0.1.0

An experimental embedded SQL-like DBMS
Documentation
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()
                    }
                )
            }
        }
    }
}