1use std::{fmt, io};
4
5use crate::{
6 ElementId, IncidenceId, IndexId, LabelId, ProjectionId, PropertyKeyId, RelationId,
7 RelationTypeId, RoleId, catalog::PropertyFamily, value::PropertyType,
8};
9
10#[derive(Debug)]
16#[non_exhaustive]
17pub enum DbError {
18 AlreadyExists,
20 NotFound,
22 IdOverflow,
24 TransactionIdOverflow,
26 CommitSeqOverflow,
28 DuplicateCatalogName,
30 DuplicateId,
32 UnknownElement {
34 id: ElementId,
36 },
37 UnknownRelation {
39 id: RelationId,
41 },
42 UnknownIncidence {
44 id: IncidenceId,
46 },
47 UnknownRole {
49 id: RoleId,
51 },
52 UnknownLabel {
54 id: LabelId,
56 },
57 UnknownRelationType {
59 id: RelationTypeId,
61 },
62 UnknownPropertyKey {
64 id: PropertyKeyId,
66 },
67 UnknownProjection {
69 id: ProjectionId,
71 },
72 UnknownIndex {
74 id: IndexId,
76 },
77 PropertyTypeMismatch {
79 expected: PropertyType,
81 actual: PropertyType,
83 },
84 WrongPropertyFamily {
86 expected: PropertyFamily,
88 actual: PropertyFamily,
90 },
91 InvalidProjection {
93 message: String,
95 },
96 EmptyQuery,
98 UnsupportedQuery {
100 message: String,
102 },
103 InvalidStore {
105 message: String,
107 },
108 Io {
110 operation: &'static str,
112 source: io::Error,
114 },
115 Codec {
117 source: serde_json::Error,
119 },
120}
121
122impl DbError {
123 pub(crate) const fn io(operation: &'static str, source: io::Error) -> Self {
129 Self::Io { operation, source }
130 }
131
132 pub(crate) fn unsupported(message: impl Into<String>) -> Self {
138 Self::UnsupportedQuery {
139 message: message.into(),
140 }
141 }
142
143 pub(crate) fn invalid_projection(message: impl Into<String>) -> Self {
149 Self::InvalidProjection {
150 message: message.into(),
151 }
152 }
153
154 pub(crate) fn invalid_store(message: impl Into<String>) -> Self {
160 Self::InvalidStore {
161 message: message.into(),
162 }
163 }
164}
165
166impl fmt::Display for DbError {
167 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
168 match self {
169 Self::AlreadyExists => formatter.write_str("database already exists"),
170 Self::NotFound => formatter.write_str("database not found"),
171 Self::IdOverflow => formatter.write_str("database ID overflow"),
172 Self::TransactionIdOverflow => formatter.write_str("transaction ID overflow"),
173 Self::CommitSeqOverflow => formatter.write_str("commit sequence overflow"),
174 Self::DuplicateCatalogName => formatter.write_str("duplicate catalog name"),
175 Self::DuplicateId => formatter.write_str("duplicate ID"),
176 Self::UnknownElement { id } => write!(formatter, "unknown element {}", id.get()),
177 Self::UnknownRelation { id } => write!(formatter, "unknown relation {}", id.get()),
178 Self::UnknownIncidence { id } => write!(formatter, "unknown incidence {}", id.get()),
179 Self::UnknownRole { id } => write!(formatter, "unknown role {}", id.get()),
180 Self::UnknownLabel { id } => write!(formatter, "unknown label {}", id.get()),
181 Self::UnknownRelationType { id } => {
182 write!(formatter, "unknown relation type {}", id.get())
183 }
184 Self::UnknownPropertyKey { id } => {
185 write!(formatter, "unknown property key {}", id.get())
186 }
187 Self::UnknownProjection { id } => write!(formatter, "unknown projection {}", id.get()),
188 Self::UnknownIndex { id } => write!(formatter, "unknown index {}", id.get()),
189 Self::PropertyTypeMismatch { expected, actual } => {
190 write!(
191 formatter,
192 "property type mismatch: expected {expected:?}, got {actual:?}"
193 )
194 }
195 Self::WrongPropertyFamily { expected, actual } => {
196 write!(
197 formatter,
198 "property family mismatch: expected {expected:?}, got {actual:?}"
199 )
200 }
201 Self::InvalidProjection { message } => {
202 write!(formatter, "invalid projection: {message}")
203 }
204 Self::EmptyQuery => formatter.write_str("empty query"),
205 Self::UnsupportedQuery { message } => write!(formatter, "unsupported query: {message}"),
206 Self::InvalidStore { message } => write!(formatter, "invalid store: {message}"),
207 Self::Io { operation, source } => write!(formatter, "{operation} failed: {source}"),
208 Self::Codec { source } => write!(formatter, "codec error: {source}"),
209 }
210 }
211}
212
213impl std::error::Error for DbError {
214 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
215 match self {
216 Self::Io { source, .. } => Some(source),
217 Self::Codec { source } => Some(source),
218 Self::AlreadyExists
219 | Self::NotFound
220 | Self::IdOverflow
221 | Self::TransactionIdOverflow
222 | Self::CommitSeqOverflow
223 | Self::DuplicateCatalogName
224 | Self::DuplicateId
225 | Self::UnknownElement { .. }
226 | Self::UnknownRelation { .. }
227 | Self::UnknownIncidence { .. }
228 | Self::UnknownRole { .. }
229 | Self::UnknownLabel { .. }
230 | Self::UnknownRelationType { .. }
231 | Self::UnknownPropertyKey { .. }
232 | Self::UnknownProjection { .. }
233 | Self::UnknownIndex { .. }
234 | Self::PropertyTypeMismatch { .. }
235 | Self::WrongPropertyFamily { .. }
236 | Self::InvalidProjection { .. }
237 | Self::EmptyQuery
238 | Self::UnsupportedQuery { .. }
239 | Self::InvalidStore { .. } => None,
240 }
241 }
242}
243
244impl From<serde_json::Error> for DbError {
245 fn from(source: serde_json::Error) -> Self {
246 Self::Codec { source }
247 }
248}