spacetimedb_sql_parser/ast/
mod.rsuse std::fmt::{Display, Formatter};
use sqlparser::ast::Ident;
pub mod sql;
pub mod sub;
#[derive(Debug)]
pub enum SqlFrom {
Expr(SqlIdent, SqlIdent),
Join(SqlIdent, SqlIdent, Vec<SqlJoin>),
}
impl SqlFrom {
pub fn has_unqualified_vars(&self) -> bool {
match self {
Self::Join(_, _, joins) => joins.iter().any(|join| join.has_unqualified_vars()),
_ => false,
}
}
}
#[derive(Debug)]
pub struct SqlJoin {
pub var: SqlIdent,
pub alias: SqlIdent,
pub on: Option<SqlExpr>,
}
impl SqlJoin {
pub fn has_unqualified_vars(&self) -> bool {
self.on.as_ref().is_some_and(|expr| expr.has_unqualified_vars())
}
}
#[derive(Debug)]
pub struct ProjectElem(pub ProjectExpr, pub SqlIdent);
impl ProjectElem {
pub fn qualify_vars(self, with: SqlIdent) -> Self {
let Self(expr, alias) = self;
Self(expr.qualify_vars(with), alias)
}
}
#[derive(Debug)]
pub enum ProjectExpr {
Var(SqlIdent),
Field(SqlIdent, SqlIdent),
}
impl From<ProjectExpr> for SqlExpr {
fn from(value: ProjectExpr) -> Self {
match value {
ProjectExpr::Var(name) => Self::Var(name),
ProjectExpr::Field(table, field) => Self::Field(table, field),
}
}
}
impl ProjectExpr {
pub fn qualify_vars(self, with: SqlIdent) -> Self {
match self {
Self::Var(name) => Self::Field(with, name),
Self::Field(_, _) => self,
}
}
}
#[derive(Debug)]
pub enum Project {
Star(Option<SqlIdent>),
Exprs(Vec<ProjectElem>),
}
impl Project {
pub fn qualify_vars(self, with: SqlIdent) -> Self {
match self {
Self::Star(..) => self,
Self::Exprs(elems) => Self::Exprs(elems.into_iter().map(|elem| elem.qualify_vars(with.clone())).collect()),
}
}
pub fn has_unqualified_vars(&self) -> bool {
match self {
Self::Exprs(exprs) => exprs
.iter()
.any(|ProjectElem(expr, _)| matches!(expr, ProjectExpr::Var(_))),
_ => false,
}
}
}
#[derive(Debug)]
pub enum SqlExpr {
Lit(SqlLiteral),
Var(SqlIdent),
Field(SqlIdent, SqlIdent),
Bin(Box<SqlExpr>, Box<SqlExpr>, BinOp),
Log(Box<SqlExpr>, Box<SqlExpr>, LogOp),
}
impl SqlExpr {
pub fn qualify_vars(self, with: SqlIdent) -> Self {
match self {
Self::Var(name) => Self::Field(with, name),
Self::Lit(..) | Self::Field(..) => self,
Self::Bin(a, b, op) => Self::Bin(
Box::new(a.qualify_vars(with.clone())),
Box::new(b.qualify_vars(with)),
op,
),
Self::Log(a, b, op) => Self::Log(
Box::new(a.qualify_vars(with.clone())),
Box::new(b.qualify_vars(with)),
op,
),
}
}
pub fn has_unqualified_vars(&self) -> bool {
match self {
Self::Var(_) => true,
Self::Bin(a, b, _) | Self::Log(a, b, _) => a.has_unqualified_vars() || b.has_unqualified_vars(),
_ => false,
}
}
}
#[derive(Debug, Clone)]
pub struct SqlIdent(pub Box<str>);
impl From<Ident> for SqlIdent {
fn from(Ident { value, .. }: Ident) -> Self {
SqlIdent(value.into_boxed_str())
}
}
#[derive(Debug)]
pub enum SqlLiteral {
Bool(bool),
Hex(Box<str>),
Num(Box<str>),
Str(Box<str>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
Eq,
Ne,
Lt,
Gt,
Lte,
Gte,
}
impl Display for BinOp {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Eq => write!(f, "="),
Self::Ne => write!(f, "<>"),
Self::Lt => write!(f, "<"),
Self::Gt => write!(f, ">"),
Self::Lte => write!(f, "<="),
Self::Gte => write!(f, ">="),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogOp {
And,
Or,
}
impl Display for LogOp {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::And => write!(f, "AND"),
Self::Or => write!(f, "OR"),
}
}
}