use thiserror::Error;
use crate::planning::plan::factorization::FactorizationError;
#[derive(Error, Debug, Clone)]
pub enum OptimizeError {
#[error("Unsupported node type: {0}")]
UnsupportedNodeType(String),
#[error("Missing statistics: {0}")]
MissingStatistics(String),
#[error("Calculation error: {0}")]
CalculationError(String),
#[error("Plan optimization error: {0}")]
PlanOptimizationError(String),
#[error("Rule application error: {0}")]
RuleApplicationError(String),
#[error("Statistics error: {0}")]
StatisticsError(String),
#[error("Index selection error: {0}")]
IndexSelectionError(String),
#[error("Join order optimization error: {0}")]
JoinOrderError(String),
#[error("Expression transform error: {0}")]
ExpressionTransformError(String),
#[error("Internal optimization error: {0}")]
InternalError(String),
#[error("Heuristic optimization failed: {0}")]
HeuristicFailed(String),
#[error("Cost-based optimization failed: {0}")]
CostBasedFailed(String),
#[error("Pipeline configuration error: {0}")]
ConfigurationError(String),
#[error("Factorization error: {0}")]
FactorizationError(
#[from]
#[source]
FactorizationError,
),
}
pub type OptimizeResult<T> = Result<T, OptimizeError>;
#[derive(Error, Debug, Clone)]
pub enum CostError {
#[error("Unsupported node type: {0}")]
UnsupportedNodeType(String),
#[error("Missing statistics: {0}")]
MissingStatistics(String),
#[error("Calculation error: {0}")]
CalculationError(String),
}
pub type CostResult<T> = Result<T, CostError>;
impl From<CostError> for OptimizeError {
fn from(err: CostError) -> Self {
match err {
CostError::UnsupportedNodeType(msg) => OptimizeError::UnsupportedNodeType(msg),
CostError::MissingStatistics(msg) => OptimizeError::MissingStatistics(msg),
CostError::CalculationError(msg) => OptimizeError::CalculationError(msg),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_optimize_error_display() {
let err = OptimizeError::UnsupportedNodeType("UnknownNode".to_string());
assert!(err.to_string().contains("Unsupported node type"));
let err = OptimizeError::MissingStatistics("vertex_count".to_string());
assert!(err.to_string().contains("Missing statistics"));
}
#[test]
fn test_cost_error_conversion() {
let cost_err = CostError::CalculationError("division by zero".to_string());
let opt_err: OptimizeError = cost_err.into();
assert!(matches!(opt_err, OptimizeError::CalculationError(_)));
}
#[test]
fn test_factorization_error_preserves_structure() {
let fact_err = FactorizationError::TooManyUnflatGroups(3);
let opt_err: OptimizeError = fact_err.clone().into();
match &opt_err {
OptimizeError::FactorizationError(inner) => {
assert_eq!(*inner, fact_err);
assert_eq!(
inner.to_string(),
"at most one unflat group allowed, found 3"
);
}
other => panic!("expected FactorizationError, got {other:?}"),
}
assert!(opt_err.to_string().contains("found 3"));
let src = std::error::Error::source(&opt_err).expect("source wired");
assert!(src.downcast_ref::<FactorizationError>().is_some());
let _cloned = opt_err.clone();
}
}