use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CancellationReason {
#[default]
UserRequest,
StatementTimeout,
LockTimeout,
IdleInTransactionSessionTimeout,
IdleSessionTimeout,
TransactionTimeout,
}
impl CancellationReason {
pub const fn message(self) -> &'static str {
match self {
Self::UserRequest => "canceling statement due to user request",
Self::StatementTimeout => "canceling statement due to statement timeout",
Self::LockTimeout => "canceling statement due to lock timeout",
Self::IdleInTransactionSessionTimeout => {
"terminating connection due to idle-in-transaction timeout"
}
Self::IdleSessionTimeout => "terminating connection due to idle-session timeout",
Self::TransactionTimeout => "terminating connection due to transaction timeout",
}
}
pub const fn terminates_session(self) -> bool {
matches!(
self,
Self::IdleInTransactionSessionTimeout
| Self::IdleSessionTimeout
| Self::TransactionTimeout
)
}
pub const fn sqlstate(self) -> &'static str {
match self {
Self::UserRequest | Self::StatementTimeout => super::SQLSTATE_QUERY_CANCELED,
Self::LockTimeout => "55P03",
Self::IdleInTransactionSessionTimeout => "25P03",
Self::IdleSessionTimeout => "57P05",
Self::TransactionTimeout => "25P04",
}
}
pub(super) const fn code(self) -> u8 {
match self {
Self::UserRequest => 1,
Self::StatementTimeout => 2,
Self::LockTimeout => 3,
Self::IdleInTransactionSessionTimeout => 4,
Self::IdleSessionTimeout => 5,
Self::TransactionTimeout => 6,
}
}
pub(super) const fn from_code(code: u8) -> Self {
match code {
2 => Self::StatementTimeout,
3 => Self::LockTimeout,
4 => Self::IdleInTransactionSessionTimeout,
5 => Self::IdleSessionTimeout,
6 => Self::TransactionTimeout,
_ => Self::UserRequest,
}
}
}
#[derive(Debug, Clone, Copy, Error, PartialEq, Eq, Default)]
#[error("{}", .reason.message())]
pub struct QueryCancelled {
pub reason: CancellationReason,
}
impl QueryCancelled {
pub const USER_REQUEST: Self = Self::new(CancellationReason::UserRequest);
pub const fn new(reason: CancellationReason) -> Self {
Self { reason }
}
pub const fn sqlstate(&self) -> &'static str {
self.reason.sqlstate()
}
}