use std::fmt;
use surrealdb_types::Error as TypesError;
#[derive(Debug)]
pub(super) struct PgError {
pub(super) code: &'static str,
pub(super) message: String,
pub(super) fatal: bool,
}
impl fmt::Display for PgError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.code, self.message)
}
}
impl std::error::Error for PgError {}
impl PgError {
fn new(code: &'static str, message: impl Into<String>) -> Self {
Self {
code,
message: message.into(),
fatal: false,
}
}
pub(super) fn fatal(mut self) -> Self {
self.fatal = true;
self
}
pub(super) fn severity(&self) -> &'static str {
if self.fatal {
"FATAL"
} else {
"ERROR"
}
}
pub(super) fn too_many_connections() -> Self {
Self::new("53300", "sorry, too many clients already").fatal()
}
pub(super) fn auth_timeout() -> Self {
Self::new("57P05", "terminating connection due to authentication timeout").fatal()
}
pub(super) fn protocol(message: impl Into<String>) -> Self {
Self::new("08P01", message)
}
pub(super) fn invalid_text(message: impl Into<String>) -> Self {
Self::new("22P02", message)
}
pub(super) fn feature_not_supported(message: impl Into<String>) -> Self {
Self::new("0A000", message)
}
pub(super) fn invalid_password(message: impl Into<String>) -> Self {
Self::new("28P01", message)
}
pub(super) fn insufficient_privilege(message: impl Into<String>) -> Self {
Self::new("42501", message)
}
pub(super) fn cannot_connect_now(message: impl Into<String>) -> Self {
Self::new("57P03", message)
}
pub(super) fn syntax(message: impl Into<String>) -> Self {
Self::new("42601", message)
}
pub(super) fn in_failed_transaction(message: impl Into<String>) -> Self {
Self::new("25P02", message)
}
pub(super) fn undefined_object(message: impl Into<String>) -> Self {
Self::new("42704", message)
}
pub(super) fn invalid_statement(name: &str) -> Self {
Self::new("26000", format!("prepared statement \"{name}\" does not exist"))
}
pub(super) fn duplicate_statement(name: &str) -> Self {
Self::new("42P05", format!("prepared statement \"{name}\" already exists"))
}
pub(super) fn invalid_cursor(name: &str) -> Self {
Self::new("34000", format!("portal \"{name}\" does not exist"))
}
pub(super) fn too_many_prepared(kind: &str) -> Self {
Self::new("54000", format!("too many {kind} on this connection"))
}
pub(super) fn internal(message: impl Into<String>) -> Self {
Self::new("XX000", message)
}
}
impl From<&TypesError> for PgError {
fn from(err: &TypesError) -> Self {
let code = match err.kind_str() {
"Auth" => "28000",
"Validation" => "42601",
"NotAllowed" => "42501",
"Thrown" => "P0001",
"NotFound" => "42704",
"Configuration" => "0A000",
_ => "XX000",
};
Self::new(code, err.message())
}
}