use reblessive::Stk;
use super::mac::expected;
use super::{ParseResult, Parser};
use crate::sql::data::Assignment;
use crate::sql::statements::access::{
AccessStatement, AccessStatementGrant, AccessStatementPurge, AccessStatementRevoke,
AccessStatementShow, PurgeKind, Subject,
};
use crate::sql::statements::live::LiveFields;
use crate::sql::statements::rebuild::RebuildIndexStatement;
use crate::sql::statements::show::ShowSince;
use crate::sql::statements::{
ForeachStatement, InfoStatement, KillStatement, LiveStatement, OptionStatement,
OutputStatement, RebuildStatement, SetStatement, ShowStatement, SleepStatement, UseStatement,
};
use crate::sql::{AssignOperator, ExplainFormat, Expr, Literal, Param, TopLevelExpr};
use crate::syn::lexer::compound;
use crate::syn::parser::mac::unexpected;
use crate::syn::token::{TokenKind, t};
use crate::types::PublicDuration;
mod alter;
mod create;
mod define;
mod delete;
mod r#if;
mod insert;
mod parts;
mod relate;
mod remove;
mod select;
mod update;
mod upsert;
impl Parser<'_> {
pub(super) async fn parse_stmt_list(
&mut self,
stk: &mut Stk,
) -> ParseResult<Vec<TopLevelExpr>> {
let mut res = Vec::new();
loop {
match self.peek_kind() {
t!(";") => {
self.pop_peek();
continue;
}
t!("eof") => break,
_ => {
let stmt = stk.run(|ctx| self.parse_top_level_expr(ctx)).await?;
res.push(stmt);
if !self.eat(t!(";")) {
if self.eat(t!("eof")) {
break;
}
let token = self.peek();
if Self::kind_starts_statement(token.kind) {
self.pop_peek();
unexpected!(self,token,"the query to end", => "maybe forgot a semicolon after the previous statement?");
}
expected!(self, t!("eof"));
}
}
}
}
Ok(res)
}
pub(super) async fn parse_top_level_expr(
&mut self,
stk: &mut Stk,
) -> ParseResult<TopLevelExpr> {
let token = self.peek();
match token.kind {
t!("BEGIN") => {
self.pop_peek();
self.parse_begin()
}
t!("CANCEL") => {
self.pop_peek();
self.parse_cancel()
}
t!("COMMIT") => {
self.pop_peek();
self.parse_commit()
}
t!("KILL") => {
self.pop_peek();
self.parse_kill_stmt().map(TopLevelExpr::Kill)
}
t!("LIVE") => {
self.pop_peek();
self.parse_live_stmt(stk).await.map(|x| TopLevelExpr::Live(Box::new(x)))
}
t!("OPTION") => {
self.pop_peek();
self.parse_option_stmt().map(TopLevelExpr::Option)
}
t!("USE") => {
self.pop_peek();
self.parse_use_stmt(stk).await.map(TopLevelExpr::Use)
}
t!("ACCESS") => {
self.pop_peek();
self.parse_access(stk).await.map(|x| TopLevelExpr::Access(Box::new(x)))
}
t!("SHOW") => {
self.pop_peek();
self.parse_show_stmt().map(TopLevelExpr::Show)
}
_ => {
let covered = self.peek_kind() == t!("(");
let expr = self.parse_expr_start(stk).await?;
let span = token.span.covers(self.last_span);
if !covered {
Self::reject_letless_let(&expr, span)?;
}
Ok(TopLevelExpr::Expr(expr))
}
}
}
async fn parse_access(&mut self, stk: &mut Stk) -> ParseResult<AccessStatement> {
let ac = self.parse_ident()?;
let base = self.eat(t!("ON")).then(|| self.parse_base()).transpose()?;
let peek = self.peek();
match peek.kind {
t!("GRANT") => {
self.pop_peek();
expected!(self, t!("FOR"));
match self.peek_kind() {
t!("USER") => {
self.pop_peek();
let user = self.parse_ident()?;
Ok(AccessStatement::Grant(AccessStatementGrant {
ac,
base,
subject: Subject::User(user),
}))
}
t!("RECORD") => {
self.pop_peek();
let rid = stk.run(|ctx| self.parse_record_id(ctx)).await?;
Ok(AccessStatement::Grant(AccessStatementGrant {
ac,
base,
subject: Subject::Record(rid),
}))
}
_ => unexpected!(self, peek, "either USER or RECORD"),
}
}
t!("SHOW") => {
self.pop_peek();
match self.peek_kind() {
t!("ALL") => {
self.pop_peek();
Ok(AccessStatement::Show(AccessStatementShow {
ac,
base,
..Default::default()
}))
}
t!("GRANT") => {
self.pop_peek();
let gr = Some(self.parse_ident()?);
Ok(AccessStatement::Show(AccessStatementShow {
ac,
base,
gr,
..Default::default()
}))
}
t!("WHERE") => {
let cond = self.try_parse_condition(stk).await?;
Ok(AccessStatement::Show(AccessStatementShow {
ac,
base,
cond,
..Default::default()
}))
}
_ => unexpected!(self, peek, "one of ALL, GRANT or WHERE"),
}
}
t!("REVOKE") => {
self.pop_peek();
match self.peek_kind() {
t!("ALL") => {
self.pop_peek();
Ok(AccessStatement::Revoke(AccessStatementRevoke {
ac,
base,
..Default::default()
}))
}
t!("GRANT") => {
self.pop_peek();
let gr = Some(self.parse_ident()?);
Ok(AccessStatement::Revoke(AccessStatementRevoke {
ac,
base,
gr,
..Default::default()
}))
}
t!("WHERE") => {
let cond = self.try_parse_condition(stk).await?;
Ok(AccessStatement::Revoke(AccessStatementRevoke {
ac,
base,
cond,
..Default::default()
}))
}
_ => unexpected!(self, peek, "one of ALL, GRANT or WHERE"),
}
}
t!("PURGE") => {
self.pop_peek();
let mut kind = None;
let kind = loop {
match self.peek_kind() {
t!("EXPIRED") => {
self.pop_peek();
match kind {
None => kind = Some(PurgeKind::Expired),
Some(PurgeKind::Revoked) => kind = Some(PurgeKind::Both),
_ => unexpected!(self, peek, "ACCESS PURGE statement to end"),
}
}
t!("REVOKED") => {
self.pop_peek();
match kind {
None => kind = Some(PurgeKind::Revoked),
Some(PurgeKind::Expired) => kind = Some(PurgeKind::Both),
_ => unexpected!(self, peek, "ACCESS PURGE statement to end"),
}
}
_ => {
let Some(kind) = kind else {
unexpected!(self, peek, "EXPIRED, or REVOKED")
};
break kind;
}
}
self.eat(t!(","));
};
let grace = if self.eat(t!("FOR")) {
self.next_token_value()?
} else {
PublicDuration::default()
};
Ok(AccessStatement::Purge(AccessStatementPurge {
ac,
base,
kind,
grace,
}))
}
_ => unexpected!(self, peek, "one of GRANT, SHOW, REVOKE or PURGE"),
}
}
fn parse_begin(&mut self) -> ParseResult<TopLevelExpr> {
self.eat(t!("TRANSACTION"));
Ok(TopLevelExpr::Begin)
}
fn parse_cancel(&mut self) -> ParseResult<TopLevelExpr> {
self.eat(t!("TRANSACTION"));
Ok(TopLevelExpr::Cancel)
}
fn parse_commit(&mut self) -> ParseResult<TopLevelExpr> {
self.eat(t!("TRANSACTION"));
Ok(TopLevelExpr::Commit)
}
pub(super) async fn parse_explain_expr(&mut self, stk: &mut Stk) -> ParseResult<Expr> {
let analyze = {
let peek = self.peek();
if matches!(peek.kind, TokenKind::Identifier) {
let ident_str = self.lexer.span_str(peek.span);
if ident_str.eq_ignore_ascii_case("ANALYZE") {
self.pop_peek();
true
} else {
false
}
} else {
false
}
};
let format = {
let peek = self.peek();
if matches!(peek.kind, TokenKind::Identifier) {
let ident_str = self.lexer.span_str(peek.span);
if ident_str.eq_ignore_ascii_case("FORMAT") {
self.pop_peek();
let format_peek = self.peek();
if matches!(format_peek.kind, TokenKind::Identifier) {
let format_str = self.lexer.span_str(format_peek.span);
if format_str.eq_ignore_ascii_case("TEXT") {
self.pop_peek();
ExplainFormat::Text
} else if format_str.eq_ignore_ascii_case("JSON") {
self.pop_peek();
ExplainFormat::Json
} else {
unexpected!(self, format_peek, "TEXT or JSON")
}
} else {
unexpected!(self, format_peek, "TEXT or JSON")
}
} else {
ExplainFormat::Text }
} else {
ExplainFormat::Text }
};
let statement = stk.run(|ctx| self.parse_expr_start(ctx)).await?;
Ok(Expr::Explain {
format,
analyze,
statement: Box::new(statement),
})
}
async fn parse_use_stmt(&mut self, stk: &mut Stk) -> ParseResult<UseStatement> {
let peek = self.peek();
let stmt = match peek.kind {
t!("NAMESPACE") => {
self.pop_peek();
let ns = stk.run(|stk| self.parse_expr_field(stk)).await?;
if self.eat(t!("DATABASE")) {
let db = stk.run(|stk| self.parse_expr_field(stk)).await?;
UseStatement::NsDb(ns, db)
} else {
UseStatement::Ns(ns)
}
}
t!("DATABASE") => {
self.pop_peek();
let db = stk.run(|stk| self.parse_expr_field(stk)).await?;
UseStatement::Db(db)
}
t!("DEFAULT") => {
self.pop_peek();
UseStatement::Default
}
_ => unexpected!(self, peek, "either DATABASE or NAMESPACE"),
};
Ok(stmt)
}
pub(super) async fn parse_for_stmt(&mut self, stk: &mut Stk) -> ParseResult<ForeachStatement> {
let param = self.next_token_value()?;
expected!(self, t!("IN"));
let range = stk.run(|stk| self.parse_expr_inherit(stk)).await?;
let span = expected!(self, t!("{")).span;
let block = self.parse_block(stk, span).await?;
Ok(ForeachStatement {
param,
range,
block,
})
}
pub(super) async fn parse_info_stmt(&mut self, stk: &mut Stk) -> ParseResult<InfoStatement> {
expected!(self, t!("FOR"));
let next = self.next();
let stmt = match next.kind {
t!("ROOT") => {
let version = if self.eat(t!("VERSION")) {
Some(stk.run(|stk| self.parse_expr_inherit(stk)).await?)
} else {
None
};
let structure = self.eat(t!("STRUCTURE"));
InfoStatement::Root(structure, version)
}
t!("NAMESPACE") => {
let version = if self.eat(t!("VERSION")) {
Some(stk.run(|stk| self.parse_expr_inherit(stk)).await?)
} else {
None
};
let structure = self.eat(t!("STRUCTURE"));
InfoStatement::Ns(structure, version)
}
t!("DATABASE") => {
let version = if self.eat(t!("VERSION")) {
Some(stk.run(|stk| self.parse_expr_inherit(stk)).await?)
} else {
None
};
let structure = self.eat(t!("STRUCTURE"));
InfoStatement::Db(structure, version)
}
t!("TABLE") => {
let ident = stk.run(|stk| self.parse_expr_table(stk)).await?;
let version = if self.eat(t!("VERSION")) {
Some(stk.run(|stk| self.parse_expr_inherit(stk)).await?)
} else {
None
};
let structure = self.eat(t!("STRUCTURE"));
InfoStatement::Tb(ident, structure, version)
}
t!("USER") => {
let ident = stk.run(|stk| self.parse_expr_inherit(stk)).await?;
let base = self.eat(t!("ON")).then(|| self.parse_base()).transpose()?;
let structure = self.eat(t!("STRUCTURE"));
InfoStatement::User(ident, base, structure)
}
t!("INDEX") => {
let index = stk.run(|stk| self.parse_expr_field(stk)).await?;
expected!(self, t!("ON"));
self.eat(t!("TABLE"));
let table = stk.run(|stk| self.parse_expr_table(stk)).await?;
let structure = self.eat(t!("STRUCTURE"));
InfoStatement::Index(index, table, structure)
}
_ => unexpected!(self, next, "an info target"),
};
Ok(stmt)
}
pub(super) fn parse_kill_stmt(&mut self) -> ParseResult<KillStatement> {
let peek = self.peek();
let id = match peek.kind {
t!("u\"") | t!("u'") => {
self.next_token_value().map(|u| Expr::Literal(Literal::Uuid(u)))?
}
t!("$param") => self.next_token_value().map(Expr::Param)?,
_ => unexpected!(self, peek, "a UUID or a parameter"),
};
Ok(KillStatement {
id,
})
}
pub(super) async fn parse_live_stmt(&mut self, stk: &mut Stk) -> ParseResult<LiveStatement> {
expected!(self, t!("SELECT"));
let fields = match self.peek_kind() {
t!("DIFF") => {
self.pop_peek();
LiveFields::Diff
}
_ => LiveFields::Select(self.parse_fields(stk).await?),
};
expected!(self, t!("FROM"));
let what = self.parse_expr_table(stk).await?;
let cond = self.try_parse_condition(stk).await?;
let fetch = self.try_parse_fetch(stk).await?;
Ok(LiveStatement {
fields,
what,
cond,
fetch,
})
}
pub(super) fn parse_option_stmt(&mut self) -> ParseResult<OptionStatement> {
let name = self.parse_ident()?;
let what = if self.eat(t!("=")) {
let next = self.next();
match next.kind {
t!("true") => true,
t!("false") => false,
_ => unexpected!(self, next, "either 'true' or 'false'"),
}
} else {
true
};
Ok(OptionStatement {
name,
what,
})
}
pub(super) fn parse_rebuild_stmt(&mut self) -> ParseResult<RebuildStatement> {
let next = self.next();
let res = match next.kind {
t!("INDEX") => {
let if_exists = if self.eat(t!("IF")) {
expected!(self, t!("EXISTS"));
true
} else {
false
};
let name = self.parse_ident()?;
expected!(self, t!("ON"));
self.eat(t!("TABLE"));
let what: crate::val::TableName = self.parse_ident_str()?.into();
let concurrently = self.eat(t!("CONCURRENTLY"));
RebuildStatement::Index(RebuildIndexStatement {
what,
name,
if_exists,
concurrently,
})
}
_ => unexpected!(self, next, "a rebuild statement keyword"),
};
Ok(res)
}
pub(super) async fn parse_return_stmt(
&mut self,
stk: &mut Stk,
) -> ParseResult<OutputStatement> {
let what = stk.run(|ctx| self.parse_expr_inherit(ctx)).await?;
let fetch = self.try_parse_fetch(stk).await?;
Ok(OutputStatement {
what,
fetch,
})
}
pub(super) async fn parse_let_stmt(&mut self, stk: &mut Stk) -> ParseResult<SetStatement> {
let name = self.next_token_value::<Param>()?.into_strand();
let kind = if self.eat(t!(":")) {
Some(self.parse_inner_kind(stk).await?)
} else {
None
};
expected!(self, t!("="));
let what = stk.run(|stk| self.parse_expr_inherit(stk)).await?;
Ok(SetStatement {
name,
what,
kind,
})
}
pub(super) fn parse_show_stmt(&mut self) -> ParseResult<ShowStatement> {
expected!(self, t!("CHANGES"));
expected!(self, t!("FOR"));
let next = self.next();
let table = match next.kind {
t!("TABLE") => {
let table: crate::val::TableName = self.parse_ident_str()?.into();
Some(table)
}
t!("DATABASE") => None,
_ => unexpected!(self, next, "`TABLE` or `DATABASE`"),
};
expected!(self, t!("SINCE"));
let next = self.peek();
let since = match next.kind {
TokenKind::Digits => {
self.pop_peek();
let int = self.lex_compound(next, compound::integer)?.value;
ShowSince::Versionstamp(int)
}
t!("d\"") | t!("d'") => ShowSince::Timestamp(self.next_token_value()?),
_ => unexpected!(self, next, "a version stamp or a date-time"),
};
let limit = self.eat(t!("LIMIT")).then(|| self.next_token_value()).transpose()?;
Ok(ShowStatement {
table,
since,
limit,
})
}
pub(super) fn parse_sleep_stmt(&mut self) -> ParseResult<SleepStatement> {
let duration = self.next_token_value()?;
Ok(SleepStatement {
duration,
})
}
pub(super) async fn parse_assignment(&mut self, stk: &mut Stk) -> ParseResult<Assignment> {
let place = self.parse_plain_idiom(stk).await?;
let token = self.next();
let operator = match token.kind {
t!("=") => AssignOperator::Assign,
t!("+=") => AssignOperator::Add,
t!("-=") => AssignOperator::Subtract,
t!("+?=") => AssignOperator::Extend,
_ => unexpected!(self, token, "an assign operator"),
};
let value = stk.run(|stk| self.parse_expr_field(stk)).await?;
Ok(Assignment {
place,
operator,
value,
})
}
}