use std::{fmt, io};
use crate::{
ElementId, IncidenceId, IndexId, LabelId, ProjectionId, PropertyKeyId, RelationId,
RelationTypeId, RoleId, catalog::PropertyFamily, value::PropertyType,
};
#[derive(Debug)]
#[non_exhaustive]
pub enum DbError {
AlreadyExists,
NotFound,
IdOverflow,
TransactionIdOverflow,
CommitSeqOverflow,
DuplicateCatalogName,
DuplicateId,
UnknownElement {
id: ElementId,
},
UnknownRelation {
id: RelationId,
},
UnknownIncidence {
id: IncidenceId,
},
UnknownRole {
id: RoleId,
},
UnknownLabel {
id: LabelId,
},
UnknownRelationType {
id: RelationTypeId,
},
UnknownPropertyKey {
id: PropertyKeyId,
},
UnknownProjection {
id: ProjectionId,
},
UnknownIndex {
id: IndexId,
},
PropertyTypeMismatch {
expected: PropertyType,
actual: PropertyType,
},
WrongPropertyFamily {
expected: PropertyFamily,
actual: PropertyFamily,
},
InvalidProjection {
message: String,
},
EmptyQuery,
UnsupportedQuery {
message: String,
},
InvalidStore {
message: String,
},
Io {
operation: &'static str,
source: io::Error,
},
Codec {
source: serde_json::Error,
},
}
impl DbError {
pub(crate) const fn io(operation: &'static str, source: io::Error) -> Self {
Self::Io { operation, source }
}
pub(crate) fn unsupported(message: impl Into<String>) -> Self {
Self::UnsupportedQuery {
message: message.into(),
}
}
pub(crate) fn invalid_projection(message: impl Into<String>) -> Self {
Self::InvalidProjection {
message: message.into(),
}
}
pub(crate) fn invalid_store(message: impl Into<String>) -> Self {
Self::InvalidStore {
message: message.into(),
}
}
}
impl fmt::Display for DbError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AlreadyExists => formatter.write_str("database already exists"),
Self::NotFound => formatter.write_str("database not found"),
Self::IdOverflow => formatter.write_str("database ID overflow"),
Self::TransactionIdOverflow => formatter.write_str("transaction ID overflow"),
Self::CommitSeqOverflow => formatter.write_str("commit sequence overflow"),
Self::DuplicateCatalogName => formatter.write_str("duplicate catalog name"),
Self::DuplicateId => formatter.write_str("duplicate ID"),
Self::UnknownElement { id } => write!(formatter, "unknown element {}", id.get()),
Self::UnknownRelation { id } => write!(formatter, "unknown relation {}", id.get()),
Self::UnknownIncidence { id } => write!(formatter, "unknown incidence {}", id.get()),
Self::UnknownRole { id } => write!(formatter, "unknown role {}", id.get()),
Self::UnknownLabel { id } => write!(formatter, "unknown label {}", id.get()),
Self::UnknownRelationType { id } => {
write!(formatter, "unknown relation type {}", id.get())
}
Self::UnknownPropertyKey { id } => {
write!(formatter, "unknown property key {}", id.get())
}
Self::UnknownProjection { id } => write!(formatter, "unknown projection {}", id.get()),
Self::UnknownIndex { id } => write!(formatter, "unknown index {}", id.get()),
Self::PropertyTypeMismatch { expected, actual } => {
write!(
formatter,
"property type mismatch: expected {expected:?}, got {actual:?}"
)
}
Self::WrongPropertyFamily { expected, actual } => {
write!(
formatter,
"property family mismatch: expected {expected:?}, got {actual:?}"
)
}
Self::InvalidProjection { message } => {
write!(formatter, "invalid projection: {message}")
}
Self::EmptyQuery => formatter.write_str("empty query"),
Self::UnsupportedQuery { message } => write!(formatter, "unsupported query: {message}"),
Self::InvalidStore { message } => write!(formatter, "invalid store: {message}"),
Self::Io { operation, source } => write!(formatter, "{operation} failed: {source}"),
Self::Codec { source } => write!(formatter, "codec error: {source}"),
}
}
}
impl std::error::Error for DbError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Io { source, .. } => Some(source),
Self::Codec { source } => Some(source),
Self::AlreadyExists
| Self::NotFound
| Self::IdOverflow
| Self::TransactionIdOverflow
| Self::CommitSeqOverflow
| Self::DuplicateCatalogName
| Self::DuplicateId
| Self::UnknownElement { .. }
| Self::UnknownRelation { .. }
| Self::UnknownIncidence { .. }
| Self::UnknownRole { .. }
| Self::UnknownLabel { .. }
| Self::UnknownRelationType { .. }
| Self::UnknownPropertyKey { .. }
| Self::UnknownProjection { .. }
| Self::UnknownIndex { .. }
| Self::PropertyTypeMismatch { .. }
| Self::WrongPropertyFamily { .. }
| Self::InvalidProjection { .. }
| Self::EmptyQuery
| Self::UnsupportedQuery { .. }
| Self::InvalidStore { .. } => None,
}
}
}
impl From<serde_json::Error> for DbError {
fn from(source: serde_json::Error) -> Self {
Self::Codec { source }
}
}