use spacetimedb_lib::Identity;
use crate::parser::{errors::SqlUnsupported, SqlParseResult};
use super::{Project, SqlExpr, SqlFrom, SqlIdent, SqlLiteral};
#[derive(Debug)]
pub enum SqlAst {
Select(SqlSelect),
Insert(SqlInsert),
Update(SqlUpdate),
Delete(SqlDelete),
Set(SqlSet),
Show(SqlShow),
}
impl SqlAst {
pub fn qualify_vars(self) -> Self {
match self {
Self::Select(select) => Self::Select(select.qualify_vars()),
Self::Update(SqlUpdate {
table: with,
assignments,
filter,
}) => Self::Update(SqlUpdate {
table: with.clone(),
filter: filter.map(|expr| expr.qualify_vars(with)),
assignments,
}),
Self::Delete(SqlDelete { table: with, filter }) => Self::Delete(SqlDelete {
table: with.clone(),
filter: filter.map(|expr| expr.qualify_vars(with)),
}),
_ => self,
}
}
pub fn find_unqualified_vars(self) -> SqlParseResult<Self> {
match self {
Self::Select(select) => select.find_unqualified_vars().map(Self::Select),
_ => Ok(self),
}
}
pub fn resolve_sender(self, sender_identity: Identity) -> Self {
match self {
Self::Select(select) => Self::Select(select.resolve_sender(sender_identity)),
Self::Update(update) => Self::Update(update.resolve_sender(sender_identity)),
Self::Delete(delete) => Self::Delete(delete.resolve_sender(sender_identity)),
_ => self,
}
}
}
#[derive(Debug)]
pub struct SqlSelect {
pub project: Project,
pub from: SqlFrom,
pub filter: Option<SqlExpr>,
pub limit: Option<Box<str>>,
}
impl SqlSelect {
pub fn qualify_vars(self) -> Self {
match &self.from {
SqlFrom::Expr(_, alias) => Self {
project: self.project.qualify_vars(alias.clone()),
filter: self.filter.map(|expr| expr.qualify_vars(alias.clone())),
..self
},
SqlFrom::Join(..) => self,
}
}
pub fn find_unqualified_vars(self) -> SqlParseResult<Self> {
if self.from.has_unqualified_vars() {
return Err(SqlUnsupported::UnqualifiedNames.into());
}
if self.project.has_unqualified_vars() {
return Err(SqlUnsupported::UnqualifiedNames.into());
}
if let Some(expr) = &self.filter
&& expr.has_unqualified_vars()
{
return Err(SqlUnsupported::UnqualifiedNames.into());
}
Ok(self)
}
pub fn resolve_sender(self, sender_identity: Identity) -> Self {
Self {
filter: self.filter.map(|expr| expr.resolve_sender(sender_identity)),
..self
}
}
}
#[derive(Debug)]
pub struct SqlInsert {
pub table: SqlIdent,
pub fields: Vec<SqlIdent>,
pub values: SqlValues,
}
#[derive(Debug)]
pub struct SqlValues(pub Vec<Vec<SqlLiteral>>);
#[derive(Debug)]
pub struct SqlUpdate {
pub table: SqlIdent,
pub assignments: Vec<SqlSet>,
pub filter: Option<SqlExpr>,
}
impl SqlUpdate {
fn resolve_sender(self, sender_identity: Identity) -> Self {
Self {
filter: self.filter.map(|expr| expr.resolve_sender(sender_identity)),
..self
}
}
}
#[derive(Debug)]
pub struct SqlDelete {
pub table: SqlIdent,
pub filter: Option<SqlExpr>,
}
impl SqlDelete {
fn resolve_sender(self, sender_identity: Identity) -> Self {
Self {
filter: self.filter.map(|expr| expr.resolve_sender(sender_identity)),
..self
}
}
}
#[derive(Debug)]
pub struct SqlSet(pub SqlIdent, pub SqlLiteral);
#[derive(Debug)]
pub struct SqlShow(pub SqlIdent);