use actix_web::http::StatusCode;
use serde_json::json;
use crate::error::{ErrorCategory, ProcessedError, generate_trace_id};
pub fn process_tokio_postgres_error(
err: &tokio_postgres::Error,
context: Option<&str>,
) -> ProcessedError {
let trace_id = generate_trace_id();
if let Some(db_err) = err.as_db_error() {
let code = db_err.code().code();
let message = db_err.message().to_string();
let (status, error_code, category) = match code {
"23505" => (
StatusCode::CONFLICT,
"unique_violation",
ErrorCategory::DatabaseConstraint,
),
"23503" => (
StatusCode::CONFLICT,
"foreign_key_violation",
ErrorCategory::DatabaseConstraint,
),
"23502" => (
StatusCode::BAD_REQUEST,
"not_null_violation",
ErrorCategory::DatabaseConstraint,
),
_ if code.starts_with("22") => (
StatusCode::BAD_REQUEST,
"data_exception",
ErrorCategory::QuerySyntax,
),
_ if code.starts_with("42") => (
StatusCode::BAD_REQUEST,
"query_syntax",
ErrorCategory::QuerySyntax,
),
_ => (
StatusCode::INTERNAL_SERVER_ERROR,
"db_error",
ErrorCategory::Internal,
),
};
let mut processed = ProcessedError::new(category, status, error_code, message, trace_id)
.with_metadata("sql_state", json!(code));
if let Some(ctx) = context {
processed = processed.with_metadata("context", json!(ctx));
}
return processed;
}
let mut processed = ProcessedError::new(
ErrorCategory::DatabaseConnection,
StatusCode::BAD_GATEWAY,
"postgres_driver_error",
err.to_string(),
trace_id,
);
if let Some(ctx) = context {
processed = processed.with_metadata("context", json!(ctx));
}
processed
}
pub fn process_tokio_postgres_db_error(
sql_state: &str,
message: &str,
context: Option<&str>,
) -> ProcessedError {
let trace_id = generate_trace_id();
let (status, error_code, category) = match sql_state {
"23505" => (
StatusCode::CONFLICT,
"unique_violation",
ErrorCategory::DatabaseConstraint,
),
"23503" => (
StatusCode::CONFLICT,
"foreign_key_violation",
ErrorCategory::DatabaseConstraint,
),
"23502" => (
StatusCode::BAD_REQUEST,
"not_null_violation",
ErrorCategory::DatabaseConstraint,
),
_ if sql_state.starts_with("22") => (
StatusCode::BAD_REQUEST,
"data_exception",
ErrorCategory::QuerySyntax,
),
_ if sql_state.starts_with("42") => (
StatusCode::BAD_REQUEST,
"query_syntax",
ErrorCategory::QuerySyntax,
),
_ => (
StatusCode::INTERNAL_SERVER_ERROR,
"db_error",
ErrorCategory::Internal,
),
};
let mut processed =
ProcessedError::new(category, status, error_code, message.to_string(), trace_id)
.with_metadata("sql_state", json!(sql_state));
if let Some(ctx) = context {
processed = processed.with_metadata("context", json!(ctx));
}
processed
}