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 Traversal {
122 source: oxgraph_algo::BfsError,
124 },
125}
126
127impl DbError {
128 pub(crate) const fn io(operation: &'static str, source: io::Error) -> Self {
134 Self::Io { operation, source }
135 }
136
137 pub(crate) fn unsupported(message: impl Into<String>) -> Self {
143 Self::UnsupportedQuery {
144 message: message.into(),
145 }
146 }
147
148 pub(crate) fn invalid_projection(message: impl Into<String>) -> Self {
154 Self::InvalidProjection {
155 message: message.into(),
156 }
157 }
158
159 pub(crate) fn invalid_store(message: impl Into<String>) -> Self {
165 Self::InvalidStore {
166 message: message.into(),
167 }
168 }
169
170 pub(crate) const fn traversal(source: oxgraph_algo::BfsError) -> Self {
176 Self::Traversal { source }
177 }
178}
179
180impl fmt::Display for DbError {
181 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
182 match self {
183 Self::AlreadyExists => formatter.write_str("database already exists"),
184 Self::NotFound => formatter.write_str("database not found"),
185 Self::IdOverflow => formatter.write_str("database ID overflow"),
186 Self::TransactionIdOverflow => formatter.write_str("transaction ID overflow"),
187 Self::CommitSeqOverflow => formatter.write_str("commit sequence overflow"),
188 Self::DuplicateCatalogName => formatter.write_str("duplicate catalog name"),
189 Self::DuplicateId => formatter.write_str("duplicate ID"),
190 Self::UnknownElement { id } => write!(formatter, "unknown element {}", id.get()),
191 Self::UnknownRelation { id } => write!(formatter, "unknown relation {}", id.get()),
192 Self::UnknownIncidence { id } => write!(formatter, "unknown incidence {}", id.get()),
193 Self::UnknownRole { id } => write!(formatter, "unknown role {}", id.get()),
194 Self::UnknownLabel { id } => write!(formatter, "unknown label {}", id.get()),
195 Self::UnknownRelationType { id } => {
196 write!(formatter, "unknown relation type {}", id.get())
197 }
198 Self::UnknownPropertyKey { id } => {
199 write!(formatter, "unknown property key {}", id.get())
200 }
201 Self::UnknownProjection { id } => write!(formatter, "unknown projection {}", id.get()),
202 Self::UnknownIndex { id } => write!(formatter, "unknown index {}", id.get()),
203 Self::PropertyTypeMismatch { expected, actual } => {
204 write!(
205 formatter,
206 "property type mismatch: expected {expected:?}, got {actual:?}"
207 )
208 }
209 Self::WrongPropertyFamily { expected, actual } => {
210 write!(
211 formatter,
212 "property family mismatch: expected {expected:?}, got {actual:?}"
213 )
214 }
215 Self::InvalidProjection { message } => {
216 write!(formatter, "invalid projection: {message}")
217 }
218 Self::EmptyQuery => formatter.write_str("empty query"),
219 Self::UnsupportedQuery { message } => write!(formatter, "unsupported query: {message}"),
220 Self::InvalidStore { message } => write!(formatter, "invalid store: {message}"),
221 Self::Io { operation, source } => write!(formatter, "{operation} failed: {source}"),
222 Self::Codec { source } => write!(formatter, "codec error: {source}"),
223 Self::Traversal { source } => write!(formatter, "traversal error: {source}"),
224 }
225 }
226}
227
228impl std::error::Error for DbError {
229 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
230 match self {
231 Self::Io { source, .. } => Some(source),
232 Self::Codec { source } => Some(source),
233 Self::Traversal { source } => Some(source),
234 Self::AlreadyExists
235 | Self::NotFound
236 | Self::IdOverflow
237 | Self::TransactionIdOverflow
238 | Self::CommitSeqOverflow
239 | Self::DuplicateCatalogName
240 | Self::DuplicateId
241 | Self::UnknownElement { .. }
242 | Self::UnknownRelation { .. }
243 | Self::UnknownIncidence { .. }
244 | Self::UnknownRole { .. }
245 | Self::UnknownLabel { .. }
246 | Self::UnknownRelationType { .. }
247 | Self::UnknownPropertyKey { .. }
248 | Self::UnknownProjection { .. }
249 | Self::UnknownIndex { .. }
250 | Self::PropertyTypeMismatch { .. }
251 | Self::WrongPropertyFamily { .. }
252 | Self::InvalidProjection { .. }
253 | Self::EmptyQuery
254 | Self::UnsupportedQuery { .. }
255 | Self::InvalidStore { .. } => None,
256 }
257 }
258}
259
260impl From<serde_json::Error> for DbError {
261 fn from(source: serde_json::Error) -> Self {
262 Self::Codec { source }
263 }
264}