///|
// TCL (Transaction Control Language) parsing functions
///|
fn Parser::parse_begin_statement(
self : Parser,
tokens : ArrayView[Token],
) -> ParserResult[BeginStmt] raise ParserError {
let tokens = self.expect_token(tokens, Keyword(Begin))
// Parse optional WORK or TRANSACTION keywords
let mut work = false
let mut transaction = false
let tokens = match tokens {
[Keyword(Transaction), .. tokens] => {
transaction = true
tokens
}
[Keyword(Work), .. tokens] => {
work = true
// WORK can be followed by TRANSACTION
match tokens {
[Keyword(Transaction), .. tokens] => {
transaction = true
tokens
}
_ => tokens
}
}
_ => tokens
}
({ work, transaction }, tokens)
}
///|
fn Parser::parse_start_transaction_statement(
self : Parser,
tokens : ArrayView[Token],
) -> ParserResult[BeginStmt] raise ParserError {
let tokens = self.expect_token(tokens, Keyword(Start))
let tokens = self.expect_token(tokens, Keyword(Transaction))
// START TRANSACTION is equivalent to BEGIN TRANSACTION
({ work: false, transaction: true }, tokens)
}
///|
fn Parser::parse_commit_statement(
self : Parser,
tokens : ArrayView[Token],
) -> ParserResult[CommitStmt] raise ParserError {
let tokens = self.expect_token(tokens, Keyword(Commit))
// Parse optional WORK or TRANSACTION keywords
let mut work = false
let mut transaction = false
let tokens = match tokens {
[Keyword(Transaction), .. tokens] => {
transaction = true
tokens
}
[Keyword(Work), .. tokens] => {
work = true
// WORK can be followed by TRANSACTION
match tokens {
[Keyword(Transaction), .. tokens] => {
transaction = true
tokens
}
_ => tokens
}
}
_ => tokens
}
({ work, transaction }, tokens)
}
///|
fn Parser::parse_rollback_statement(
self : Parser,
tokens : ArrayView[Token],
) -> ParserResult[RollbackStmt] raise ParserError {
let tokens = self.expect_token(tokens, Keyword(Rollback))
// Parse optional WORK or TRANSACTION keywords
let mut work = false
let mut transaction = false
let mut savepoint : String? = None
let tokens = match tokens {
[Keyword(Transaction), .. tokens] => {
transaction = true
tokens
}
[Keyword(Work), .. tokens] => {
work = true
// WORK can be followed by TRANSACTION
match tokens {
[Keyword(Transaction), .. tokens] => {
transaction = true
tokens
}
_ => tokens
}
}
_ => tokens
}
// Parse optional TO [SAVEPOINT] savepoint_name
let tokens = match tokens {
[Keyword(To), Keyword(Savepoint), Identifier(name), .. tokens] => {
savepoint = Option::Some(name)
tokens
}
[Keyword(To), Identifier(name), .. tokens] => {
savepoint = Option::Some(name)
tokens
}
_ => tokens
}
({ work, transaction, savepoint }, tokens)
}
///|
fn Parser::parse_savepoint_statement(
self : Parser,
tokens : ArrayView[Token],
) -> ParserResult[SavepointStmt] raise ParserError {
let tokens = self.expect_token(tokens, Keyword(Savepoint))
let (name, tokens) = match tokens {
[Identifier(name), .. tokens] => (name, tokens)
[token, .. _tokens] =>
raise UnexpectedTokenMessageError(token, "expected savepoint name")
[] =>
raise InternalBug("parse_savepoint_statement: unexpected end of tokens")
}
({ name, }, tokens)
}
///|
fn Parser::parse_release_savepoint_statement(
self : Parser,
tokens : ArrayView[Token],
) -> ParserResult[ReleaseSavepointStmt] raise ParserError {
let tokens = self.expect_token(tokens, Keyword(Release))
// Parse optional SAVEPOINT keyword
let mut savepoint_keyword = false
let tokens = match tokens {
[Keyword(Savepoint), .. tokens] => {
savepoint_keyword = true
tokens
}
_ => tokens
}
let (name, tokens) = match tokens {
[Identifier(name), .. tokens] => (name, tokens)
[token, .. _tokens] =>
raise UnexpectedTokenMessageError(token, "expected savepoint name")
[] =>
raise InternalBug(
"parse_release_savepoint_statement: unexpected end of tokens",
)
}
({ savepoint_keyword, name }, tokens)
}
///|
// TCL statement tests
test "BEGIN statement" {
let tokens = "BEGIN;"
let stmt = parse_sql(tokens)[0] |> pretty_print
inspect(
stmt,
content=(
#|BEGIN;
),
)
}
///|
test "BEGIN WORK statement" {
let tokens = "BEGIN WORK;"
let stmt = parse_sql(tokens)[0] |> pretty_print
inspect(
stmt,
content=(
#|BEGIN WORK;
),
)
}
///|
test "BEGIN TRANSACTION statement" {
let tokens = "BEGIN TRANSACTION;"
let stmt = parse_sql(tokens)[0] |> pretty_print
inspect(
stmt,
content=(
#|BEGIN TRANSACTION;
),
)
}
///|
test "START TRANSACTION statement" {
let tokens = "START TRANSACTION;"
let stmt = parse_sql(tokens)[0] |> pretty_print
inspect(
stmt,
content=(
#|BEGIN TRANSACTION;
),
)
}
///|
test "COMMIT statement" {
let tokens = "COMMIT;"
let stmt = parse_sql(tokens)[0] |> pretty_print
inspect(
stmt,
content=(
#|COMMIT;
),
)
}
///|
test "COMMIT WORK statement" {
let tokens = "COMMIT WORK;"
let stmt = parse_sql(tokens)[0] |> pretty_print
inspect(
stmt,
content=(
#|COMMIT WORK;
),
)
}
///|
test "ROLLBACK statement" {
let tokens = "ROLLBACK;"
let stmt = parse_sql(tokens)[0] |> pretty_print
inspect(
stmt,
content=(
#|ROLLBACK;
),
)
}
///|
test "ROLLBACK TO SAVEPOINT statement" {
let tokens = "ROLLBACK TO SAVEPOINT sp1;"
let stmt = parse_sql(tokens)[0] |> pretty_print
inspect(
stmt,
content=(
#|ROLLBACK TO SAVEPOINT sp1;
),
)
}
///|
test "SAVEPOINT statement" {
let tokens = "SAVEPOINT sp1;"
let stmt = parse_sql(tokens)[0] |> pretty_print
inspect(
stmt,
content=(
#|SAVEPOINT sp1;
),
)
}
///|
test "RELEASE SAVEPOINT statement" {
let tokens = "RELEASE SAVEPOINT sp1;"
let stmt = parse_sql(tokens)[0] |> pretty_print
inspect(
stmt,
content=(
#|RELEASE SAVEPOINT sp1;
),
)
}