systemprompt_database/
error.rs1use thiserror::Error;
13
14#[derive(Debug, Error)]
15pub enum RepositoryError {
16 #[error("Entity not found: {0}")]
17 NotFound(String),
18
19 #[error("Constraint violation: {0}")]
20 Constraint(String),
21
22 #[error("Database error: {0}")]
23 Database(#[from] sqlx::Error),
24
25 #[error("Serialization error: {0}")]
26 Serialization(#[from] serde_json::Error),
27
28 #[error("Invalid argument: {0}")]
29 InvalidArgument(String),
30
31 #[error("Invalid state: {0}")]
32 InvalidState(String),
33
34 #[error("Internal error: {0}")]
35 Internal(String),
36
37 #[error("Failed to execute query")]
38 QueryExecution(#[source] Box<Self>),
39
40 #[error("SQL could not be split into statements: {0}")]
41 SqlSplit(#[source] pg_query::Error),
42
43 #[error("Failed to execute SQL statement: {statement}")]
44 Statement {
45 statement: String,
46 #[source]
47 source: Box<Self>,
48 },
49
50 #[error("Failed to establish database connection")]
51 Connection(#[source] Box<Self>),
52
53 #[error("Failed to read SQL file {path}")]
54 SqlFile {
55 path: String,
56 #[source]
57 source: std::io::Error,
58 },
59}
60
61pub type DatabaseResult<T> = Result<T, RepositoryError>;
62
63impl RepositoryError {
64 pub fn not_found<T: std::fmt::Display>(id: T) -> Self {
65 Self::NotFound(id.to_string())
66 }
67
68 pub fn is_serialization_failure(&self) -> bool {
69 match self {
72 Self::Database(sqlx_error) => sqlx_error.as_database_error().is_some_and(|db_error| {
73 let code = db_error.code().map(|c| c.to_string());
74 matches!(code.as_deref(), Some("40001" | "40P01"))
75 }),
76 _ => false,
77 }
78 }
79
80 pub fn is_invalid_function_definition(&self) -> bool {
84 match self {
85 Self::Database(sqlx_error) => sqlx_error
86 .as_database_error()
87 .is_some_and(|db_error| db_error.code().as_deref() == Some("42P13")),
88 _ => false,
89 }
90 }
91
92 pub fn constraint<T: Into<String>>(message: T) -> Self {
93 Self::Constraint(message.into())
94 }
95
96 pub fn invalid_argument<T: Into<String>>(message: T) -> Self {
97 Self::InvalidArgument(message.into())
98 }
99
100 pub fn internal<T: Into<String>>(message: T) -> Self {
101 Self::Internal(message.into())
102 }
103
104 pub fn invalid_state<T: Into<String>>(message: T) -> Self {
105 Self::InvalidState(message.into())
106 }
107
108 #[must_use]
109 pub const fn is_not_found(&self) -> bool {
110 matches!(self, Self::NotFound(_))
111 }
112
113 #[must_use]
114 pub const fn is_constraint(&self) -> bool {
115 matches!(self, Self::Constraint(_))
116 }
117}
118
119impl From<RepositoryError> for systemprompt_traits::RepositoryError {
120 fn from(err: RepositoryError) -> Self {
121 Self::database(err)
122 }
123}