use surrealdb_types::{SqlFormat, ToSql};
use crate::dbs::QueryType;
use crate::expr::statements::OptionStatement;
use crate::observe::StatementType;
use crate::{expr, sql};
pub(crate) enum TopLevelStatement {
Ast(sql::TopLevelExpr),
Plan(expr::TopLevelExpr),
}
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum Dispatch {
Begin,
Cancel,
Commit,
Option(OptionStatement),
Runnable,
}
impl TopLevelStatement {
pub(crate) fn dispatch(&self) -> Dispatch {
match self {
TopLevelStatement::Ast(stmt) => match stmt {
sql::TopLevelExpr::Begin => Dispatch::Begin,
sql::TopLevelExpr::Cancel => Dispatch::Cancel,
sql::TopLevelExpr::Commit => Dispatch::Commit,
sql::TopLevelExpr::Option(stmt) => Dispatch::Option(stmt.clone().into()),
sql::TopLevelExpr::Access(_)
| sql::TopLevelExpr::Kill(_)
| sql::TopLevelExpr::Live(_)
| sql::TopLevelExpr::Use(_)
| sql::TopLevelExpr::Show(_)
| sql::TopLevelExpr::Expr(_) => Dispatch::Runnable,
},
TopLevelStatement::Plan(stmt) => match stmt {
expr::TopLevelExpr::Begin => Dispatch::Begin,
expr::TopLevelExpr::Cancel => Dispatch::Cancel,
expr::TopLevelExpr::Commit => Dispatch::Commit,
expr::TopLevelExpr::Option(stmt) => Dispatch::Option(stmt.clone()),
expr::TopLevelExpr::Access(_)
| expr::TopLevelExpr::Kill(_)
| expr::TopLevelExpr::Live(_)
| expr::TopLevelExpr::Use(_)
| expr::TopLevelExpr::Show(_)
| expr::TopLevelExpr::Expr(_) => Dispatch::Runnable,
},
}
}
pub(crate) fn read_only(&self) -> bool {
match self {
TopLevelStatement::Ast(stmt) => stmt.read_only(),
TopLevelStatement::Plan(stmt) => stmt.read_only(),
}
}
pub(crate) fn kind_reads_only(&self) -> bool {
kind_reads_only(self.statement_type())
}
pub(crate) fn statement_type(&self) -> StatementType {
match self {
TopLevelStatement::Ast(stmt) => sql_statement_type(stmt),
TopLevelStatement::Plan(stmt) => expr_statement_type(stmt),
}
}
pub(crate) fn query_type(&self) -> QueryType {
query_type(self.statement_type())
}
pub(crate) fn into_expr(self) -> expr::TopLevelExpr {
match self {
TopLevelStatement::Ast(stmt) => stmt.into(),
TopLevelStatement::Plan(stmt) => stmt,
}
}
}
impl ToSql for TopLevelStatement {
fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
match self {
TopLevelStatement::Ast(stmt) => {
let lowered: expr::TopLevelExpr = stmt.clone().into();
lowered.fmt_sql(f, fmt);
}
TopLevelStatement::Plan(stmt) => stmt.fmt_sql(f, fmt),
}
}
}
fn kind_reads_only(kind: StatementType) -> bool {
matches!(
kind,
StatementType::Use
| StatementType::Show
| StatementType::Select
| StatementType::Info
| StatementType::Explain
)
}
fn query_type(kind: StatementType) -> QueryType {
match kind {
StatementType::Live => QueryType::Live,
StatementType::Kill => QueryType::Kill,
_ => QueryType::Other,
}
}
fn sql_statement_type(expr: &sql::TopLevelExpr) -> StatementType {
match expr {
sql::TopLevelExpr::Begin => StatementType::Begin,
sql::TopLevelExpr::Cancel => StatementType::Cancel,
sql::TopLevelExpr::Commit => StatementType::Commit,
sql::TopLevelExpr::Access(_) => StatementType::Access,
sql::TopLevelExpr::Kill(_) => StatementType::Kill,
sql::TopLevelExpr::Live(_) => StatementType::Live,
sql::TopLevelExpr::Option(_) => StatementType::Option,
sql::TopLevelExpr::Use(_) => StatementType::Use,
sql::TopLevelExpr::Show(_) => StatementType::Show,
sql::TopLevelExpr::Expr(expr) => sql_expr_statement_type(expr),
}
}
fn sql_expr_statement_type(expr: &sql::Expr) -> StatementType {
match expr {
sql::Expr::Select(_) => StatementType::Select,
sql::Expr::Create(_) => StatementType::Create,
sql::Expr::Update(_) => StatementType::Update,
sql::Expr::Upsert(_) => StatementType::Upsert,
sql::Expr::Delete(_) => StatementType::Delete,
sql::Expr::Relate(_) => StatementType::Relate,
sql::Expr::Insert(_) => StatementType::Insert,
sql::Expr::Define(_) => StatementType::Define,
sql::Expr::Remove(_) => StatementType::Remove,
sql::Expr::Rebuild(_) => StatementType::Rebuild,
sql::Expr::Alter(_) => StatementType::Alter,
sql::Expr::Info(_) => StatementType::Info,
sql::Expr::Foreach(_) => StatementType::Foreach,
sql::Expr::IfElse(_) => StatementType::IfElse,
sql::Expr::Sleep(_) => StatementType::Sleep,
sql::Expr::Explain {
..
} => StatementType::Explain,
sql::Expr::Let(_) => StatementType::Let,
sql::Expr::Return(_) => StatementType::Return,
sql::Expr::Break => StatementType::Break,
sql::Expr::Continue => StatementType::Continue,
sql::Expr::Throw(_) => StatementType::Throw,
sql::Expr::Block(_) => StatementType::Block,
sql::Expr::Literal(_)
| sql::Expr::Param(_)
| sql::Expr::Idiom(_)
| sql::Expr::Table(_)
| sql::Expr::Mock(_)
| sql::Expr::Constant(_)
| sql::Expr::Prefix {
..
}
| sql::Expr::Postfix {
..
}
| sql::Expr::Binary {
..
}
| sql::Expr::FunctionCall(_)
| sql::Expr::Closure(_) => StatementType::Other,
}
}
fn expr_statement_type(expr: &expr::TopLevelExpr) -> StatementType {
match expr {
expr::TopLevelExpr::Begin => StatementType::Begin,
expr::TopLevelExpr::Cancel => StatementType::Cancel,
expr::TopLevelExpr::Commit => StatementType::Commit,
expr::TopLevelExpr::Access(_) => StatementType::Access,
expr::TopLevelExpr::Kill(_) => StatementType::Kill,
expr::TopLevelExpr::Live(_) => StatementType::Live,
expr::TopLevelExpr::Option(_) => StatementType::Option,
expr::TopLevelExpr::Use(_) => StatementType::Use,
expr::TopLevelExpr::Show(_) => StatementType::Show,
expr::TopLevelExpr::Expr(expr) => expr_expr_statement_type(expr),
}
}
fn expr_expr_statement_type(expr: &expr::Expr) -> StatementType {
match expr {
expr::Expr::Select(_) => StatementType::Select,
expr::Expr::Create(_) => StatementType::Create,
expr::Expr::Update(_) => StatementType::Update,
expr::Expr::Upsert(_) => StatementType::Upsert,
expr::Expr::Delete(_) => StatementType::Delete,
expr::Expr::Relate(_) => StatementType::Relate,
expr::Expr::Insert(_) => StatementType::Insert,
expr::Expr::Define(_) => StatementType::Define,
expr::Expr::Remove(_) => StatementType::Remove,
expr::Expr::Rebuild(_) => StatementType::Rebuild,
expr::Expr::Alter(_) => StatementType::Alter,
expr::Expr::Info(_) => StatementType::Info,
expr::Expr::Foreach(_) => StatementType::Foreach,
expr::Expr::IfElse(_) => StatementType::IfElse,
expr::Expr::Sleep(_) => StatementType::Sleep,
expr::Expr::Explain {
..
} => StatementType::Explain,
expr::Expr::Let(_) => StatementType::Let,
expr::Expr::Return(_) => StatementType::Return,
expr::Expr::Break => StatementType::Break,
expr::Expr::Continue => StatementType::Continue,
expr::Expr::Throw(_) => StatementType::Throw,
expr::Expr::Block(_) => StatementType::Block,
expr::Expr::Literal(_)
| expr::Expr::Param(_)
| expr::Expr::Idiom(_)
| expr::Expr::Table(_)
| expr::Expr::Mock(_)
| expr::Expr::Constant(_)
| expr::Expr::Prefix {
..
}
| expr::Expr::Postfix {
..
}
| expr::Expr::Binary {
..
}
| expr::Expr::FunctionCall(_)
| expr::Expr::Closure(_) => StatementType::Other,
expr::Expr::Match(_) => StatementType::Other,
}
}