use std::path::PathBuf;
use thiserror::Error;
use crate::{
storage::StorageError,
superfile::error::BuildError as SuperfileBuildError,
supertable::{ManifestLoadError, manifest::part},
};
#[derive(Debug, Error)]
pub enum BuildError {
#[error("no documents to build")]
NoDocsToBuild,
#[error("schema is missing the declared id_column {0:?}")]
MissingIdColumn(String),
#[error("id_column {0:?} must be Decimal128(38, 0); found {1}")]
IdColumnWrongType(String, String),
#[error(
"user schema must not contain a column named {0:?} — \
that name is reserved for the supertable-managed id column"
)]
IdColumnReserved(String),
#[error("FTS column {column:?} not found in schema")]
FtsColumnMissing { column: String },
#[error("FTS column {column:?} must be LargeUtf8; found {actual}")]
FtsColumnMustBeLargeUtf8 { column: String, actual: String },
#[error("vector column {column:?} not found in schema")]
VectorColumnMissing { column: String },
#[error("vector column {column:?} must be FixedSizeList<Float32, {dim}>; found {actual}")]
VectorColumnNotFixedSizeList {
column: String,
dim: usize,
actual: String,
},
#[error(
"vector column {column:?} declares dim={expected}; \
schema FixedSizeList list_size is {actual}"
)]
VectorColumnDimMismatch {
column: String,
expected: usize,
actual: usize,
},
#[error(
"vector column {column:?} contains null entries at row offsets {first_nulls:?}; \
null vectors are not permitted in v1"
)]
VectorColumnHasNulls {
column: String,
first_nulls: Vec<usize>,
},
#[error("vector column {column:?} declares dim={dim}; must be in [16, 4096]")]
VectorDimOutOfRange { column: String, dim: usize },
#[error("logical name {0:?} duplicated across fts_columns and vector_columns")]
DuplicateLogicalName(String),
#[error("user column name {0:?} contains reserved \\x1F separator")]
ReservedSeparatorInColumnName(String),
#[error("user column name {0:?} starts with reserved prefix 'inf.'")]
ReservedPrefixInColumnName(String),
#[error(
"FTS columns declared but no tokenizer supplied; tokenizer is required iff fts_columns is non-empty"
)]
MissingTokenizer,
#[error("input RecordBatch schema does not match the supertable's declared schema")]
BatchSchemaMismatch,
#[error("error from underlying superfile layer: {0}")]
Superfile(#[from] SuperfileBuildError),
#[error(
"another SupertableWriter is already outstanding for this Supertable; \
drop it before acquiring a new one"
)]
SupertableInUse,
#[error("superfile store: {0}")]
Store(String),
#[error("rayon thread pool creation failed: {0}")]
ThreadPoolCreation(String),
#[error("error reading the just-built superfile during commit: {0}")]
ReadAfterCommit(String),
#[error("storage construction failed: {0}")]
StorageConstruction(#[from] StorageError),
#[error("disk cache root unwritable: {0}")]
DiskCacheRootUnwritable(PathBuf),
#[error("partition column missing in schema: {0}")]
PartitionColumnMissing(String),
}
#[derive(Debug, Error)]
pub enum CommitError {
#[error("storage error during commit: {0}")]
Storage(#[from] crate::storage::StorageError),
#[error("build error during commit")]
Build(#[from] BuildError),
#[error("manifest error: {0}")]
ManifestError(#[from] ManifestError),
#[error("manifest encode failed: {0}")]
Encode(String),
#[error("pointer file parse failed: {0}")]
PointerParse(String),
#[error("write contention exhausted retries")]
WriteContentionExhausted,
}
#[derive(Debug, Error)]
pub enum ManifestError {
#[error("superfile spans partition boundary: {detail}")]
SuperfileSpansPartition { detail: String },
#[error("manifest load error: {0}")]
ManifestLoadError(#[from] ManifestLoadError),
#[error("unknown part id: {0}")]
UnknownPartId(part::PartId),
}
#[derive(Debug, Error)]
pub enum OpenError {
#[error("pointer file missing or unreadable")]
PointerUnreadable(#[source] crate::storage::StorageError),
#[error("manifest list parse failed")]
ManifestListParse(String),
#[error("manifest load error")]
ManifestLoadError(#[from] ManifestLoadError),
#[error("manifest part load failed: {part_id}")]
ManifestPartLoad {
part_id: String,
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("content-hash mismatch: expected {expected}, got {actual}")]
ContentHashMismatch { expected: String, actual: String },
#[error("storage error during open")]
Storage(#[from] crate::storage::StorageError),
#[error("build error during open")]
Build(#[from] BuildError),
#[error("commit error during open")]
Commit(#[from] CommitError),
}
#[derive(Debug, thiserror::Error)]
pub enum OptimizeError {
#[error("optimize requires a storage backend")]
NoStorage,
#[error("superfile {0} not found in manifest snapshot")]
SuperfileNotFound(uuid::Uuid),
#[error("empty merged superfile")]
EmptyMergedSuperfile,
#[error(
"tombstone sidecar for {superfile_id} already sealed by compaction {existing_compaction_id}"
)]
SidecarConflict {
superfile_id: uuid::Uuid,
existing_compaction_id: uuid::Uuid,
},
#[error("seal failed: {0}")]
Seal(String),
#[error("failed to build superfile: {0}")]
Build(String),
#[error("failed to commit: {0}")]
Commit(String),
#[error("post-commit manifest refresh failed: {0}")]
Refresh(String),
#[error("optimize already in progress on this handle")]
AlreadyRunning,
}
impl From<CompactionError> for OptimizeError {
fn from(e: CompactionError) -> Self {
match e {
CompactionError::NoStorage => OptimizeError::NoStorage,
CompactionError::SuperfileNotFound(id) => OptimizeError::SuperfileNotFound(id),
CompactionError::EmptyMergedSuperfile => OptimizeError::EmptyMergedSuperfile,
CompactionError::SidecarConflict {
superfile_id,
existing_compaction_id,
} => OptimizeError::SidecarConflict {
superfile_id,
existing_compaction_id,
},
CompactionError::Seal(s) => OptimizeError::Seal(s),
CompactionError::Build(s) => OptimizeError::Build(s),
CompactionError::Commit(s) => OptimizeError::Commit(s),
CompactionError::Refresh(s) => OptimizeError::Refresh(s),
CompactionError::AlreadyCompacting => OptimizeError::AlreadyRunning,
}
}
}
#[derive(Debug, thiserror::Error)]
pub(crate) enum CompactionError {
#[error("compaction requires a storage backend")]
NoStorage,
#[error("superfile {0} not found in manifest snapshot")]
SuperfileNotFound(uuid::Uuid),
#[error("empty merged superfile")]
EmptyMergedSuperfile,
#[error(
"tombstone sidecar for {superfile_id} already sealed by compaction {existing_compaction_id}"
)]
SidecarConflict {
superfile_id: uuid::Uuid,
existing_compaction_id: uuid::Uuid,
},
#[error("seal failed: {0}")]
Seal(String),
#[error("failed to build superfile: {0}")]
Build(String),
#[error("failed to commit compaction: {0}")]
Commit(String),
#[error("post-commit manifest refresh failed: {0}")]
Refresh(String),
#[error("compaction already in progress on this supertable handle")]
AlreadyCompacting,
}
#[derive(Debug, thiserror::Error)]
pub enum GcError {
#[error("gc requires a storage backend")]
NoStorage,
#[error("storage error during gc: {0}")]
Storage(#[from] crate::storage::StorageError),
}
#[derive(Debug, Error)]
pub enum QueryError {
#[error("superfile store error during query: {0}")]
Store(String),
#[error("error reading parquet bytes during scan: {0}")]
Parquet(String),
#[error("DataFusion failed to plan the query: {0}")]
Plan(String),
#[error("DataFusion failed to execute the query: {0}")]
Execute(String),
#[error("manifest load error: {0}")]
ManifestLoad(ManifestLoadError),
}