uqa_sql/semantics/effects/
transaction_blocks.rs1use crate::SQLError;
10
11pub fn transaction_requires_explicit_block(transaction: &crate::ast::TransactionStmt) -> bool {
12 matches!(
13 transaction,
14 crate::ast::TransactionStmt::Savepoint(_)
15 | crate::ast::TransactionStmt::ReleaseSavepoint(_)
16 | crate::ast::TransactionStmt::RollbackToSavepoint(_)
17 | crate::ast::TransactionStmt::CommitAndChain
18 | crate::ast::TransactionStmt::RollbackAndChain
19 )
20}
21
22pub fn no_active_transaction_error(transaction: &crate::ast::TransactionStmt) -> SQLError {
23 let command = match transaction {
24 crate::ast::TransactionStmt::Savepoint(_) => "SAVEPOINT",
25 crate::ast::TransactionStmt::ReleaseSavepoint(_) => "RELEASE SAVEPOINT",
26 crate::ast::TransactionStmt::RollbackToSavepoint(_) => "ROLLBACK TO SAVEPOINT",
27 crate::ast::TransactionStmt::CommitAndChain => "COMMIT AND CHAIN",
28 crate::ast::TransactionStmt::RollbackAndChain => "ROLLBACK AND CHAIN",
29 _ => unreachable!("only explicit-block transaction commands use this error"),
30 };
31 SQLError::Routine {
32 sqlstate: "25P01".into(),
33 message: format!("{command} can only be used in transaction blocks"),
34 }
35}
36
37pub fn no_transaction_block_warning(command: &str) -> crate::SQLNotice {
39 crate::SQLNotice::warning(format!("{command} can only be used in transaction blocks"))
40 .with_sqlstate("25P01")
41}
42
43pub fn transaction_in_progress_warning() -> crate::SQLNotice {
45 crate::SQLNotice::warning("there is already a transaction in progress").with_sqlstate("25001")
46}
47
48pub fn no_transaction_in_progress_warning() -> crate::SQLNotice {
50 crate::SQLNotice::warning("there is no transaction in progress").with_sqlstate("25P01")
51}
52
53#[cfg(test)]
54mod tests {
55 use super::{no_active_transaction_error, transaction_requires_explicit_block};
56 use crate::{ast::TransactionStmt, SQLError};
57
58 #[test]
59 fn explicit_block_commands_keep_their_individual_diagnostics() {
60 for (command, spelling) in [
61 (TransactionStmt::Savepoint("s".into()), "SAVEPOINT"),
62 (
63 TransactionStmt::ReleaseSavepoint("s".into()),
64 "RELEASE SAVEPOINT",
65 ),
66 (
67 TransactionStmt::RollbackToSavepoint("s".into()),
68 "ROLLBACK TO SAVEPOINT",
69 ),
70 (TransactionStmt::CommitAndChain, "COMMIT AND CHAIN"),
71 (TransactionStmt::RollbackAndChain, "ROLLBACK AND CHAIN"),
72 ] {
73 assert!(transaction_requires_explicit_block(&command));
74 assert!(
75 matches!(no_active_transaction_error(&command), SQLError::Routine { sqlstate, message } if sqlstate == "25P01" && message == format!("{spelling} can only be used in transaction blocks"))
76 );
77 }
78 for command in [
79 TransactionStmt::Begin,
80 TransactionStmt::Commit,
81 TransactionStmt::Rollback,
82 ] {
83 assert!(!transaction_requires_explicit_block(&command));
84 }
85 }
86}