use crate::parser::ast::stmt::*;
use crate::parser::core::error::{ParseError, ParseErrorKind};
use crate::parser::parsing::parse_context::ParseContext;
use crate::parser::TokenKind;
pub struct TransactionParser;
impl Default for TransactionParser {
fn default() -> Self {
Self
}
}
impl TransactionParser {
pub fn new() -> Self {
Self
}
pub fn parse_begin_transaction(&mut self, ctx: &mut ParseContext) -> Result<Stmt, ParseError> {
let start_span = ctx.current_span();
ctx.expect_token(TokenKind::Begin)?;
if ctx.check_token(TokenKind::Transaction) {
ctx.expect_token(TokenKind::Transaction)?;
}
let mut read_only = None;
if ctx.check_token(TokenKind::Read) {
ctx.expect_token(TokenKind::Read)?;
let mode = if ctx.check_token(TokenKind::Only) {
ctx.expect_token(TokenKind::Only)?;
true
} else if ctx.check_token(TokenKind::Write) {
ctx.expect_token(TokenKind::Write)?;
false
} else {
let pos = ctx.current_position();
return Err(ParseError::new(
ParseErrorKind::UnexpectedToken,
format!(
"Expected READ ONLY or READ WRITE, found {:?}",
ctx.current_token().kind
),
pos,
)
.with_expected_tokens(vec!["READ ONLY".to_string(), "READ WRITE".to_string()]));
};
read_only = Some(mode);
}
let span = ctx.span_since(start_span.start);
Ok(Stmt::BeginTransaction(BeginTransactionStmt {
span,
read_only,
}))
}
pub fn parse_commit_transaction(&mut self, ctx: &mut ParseContext) -> Result<Stmt, ParseError> {
let start_span = ctx.current_span();
ctx.expect_token(TokenKind::Commit)?;
if ctx.check_token(TokenKind::Transaction) {
ctx.expect_token(TokenKind::Transaction)?;
}
let span = ctx.span_since(start_span.start);
Ok(Stmt::CommitTransaction(CommitTransactionStmt { span }))
}
pub fn parse_rollback_transaction(
&mut self,
ctx: &mut ParseContext,
) -> Result<Stmt, ParseError> {
let start_span = ctx.current_span();
ctx.expect_token(TokenKind::Rollback)?;
if ctx.check_token(TokenKind::Transaction) {
ctx.expect_token(TokenKind::Transaction)?;
}
let savepoint_name = if ctx.check_token(TokenKind::To) {
ctx.expect_token(TokenKind::To)?;
ctx.match_token(TokenKind::Savepoint);
Some(ctx.expect_identifier()?)
} else {
None
};
let span = ctx.span_since(start_span.start);
Ok(Stmt::RollbackTransaction(RollbackTransactionStmt {
span,
savepoint_name,
}))
}
pub fn parse_savepoint_statement(
&mut self,
ctx: &mut ParseContext,
) -> Result<Stmt, ParseError> {
let start_span = ctx.current_span();
ctx.expect_token(TokenKind::Savepoint)?;
let name = ctx.expect_identifier()?;
let span = ctx.span_since(start_span.start);
Ok(Stmt::Savepoint(SavepointStmt { span, name }))
}
pub fn parse_release_savepoint(&mut self, ctx: &mut ParseContext) -> Result<Stmt, ParseError> {
let start_span = ctx.current_span();
ctx.expect_token(TokenKind::Release)?;
ctx.expect_token(TokenKind::Savepoint)?;
let name = ctx.expect_identifier()?;
let span = ctx.span_since(start_span.start);
Ok(Stmt::ReleaseSavepoint(ReleaseSavepointStmt { span, name }))
}
}