Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/skade

skade-flight/src/error.rs

//! One error type, one mapping to the wire.
//!
//! DataFusion's planner errors (bad SQL, unknown table) are the CLIENT's
//! fault and go out as `INVALID_ARGUMENT` so an ODBC/ADBC driver shows the
//! parser's message verbatim. Everything else (catalog I/O, object store,
//! IPC encoding) is `INTERNAL`.

use datafusion::error::DataFusionError;
use tonic::Status;

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("sql: {0}")]
    Sql(String),
    /// A write (or session-view DDL) on an engine built with
    /// `EngineOptions.read_only` — the lake's own writer owns every change.
    #[error("read-only: {0}")]
    ReadOnly(String),
    #[error("datafusion: {0}")]
    DataFusion(#[from] DataFusionError),
    #[error("skade: {0}")]
    Skade(#[from] skade::SkadeError),
    #[error("iceberg: {0}")]
    Iceberg(#[from] iceberg::Error),
    #[error("arrow: {0}")]
    Arrow(#[from] arrow_schema::ArrowError),
    #[error("flight: {0}")]
    Flight(#[from] arrow_flight::error::FlightError),
    #[error("{0}")]
    Other(String),
}

pub type Result<T> = std::result::Result<T, Error>;

impl Error {
    /// Classify a DataFusion error: planner / SQL / schema errors are the
    /// caller's, and are reported as such.
    pub fn from_df(e: DataFusionError) -> Self {
        match e {
            DataFusionError::SQL(..) | DataFusionError::Plan(..) | DataFusionError::SchemaError(..) => {
                Error::Sql(e.strip_backtrace())
            }
            other => Error::DataFusion(other),
        }
    }
}

impl From<Error> for Status {
    fn from(e: Error) -> Status {
        match &e {
            Error::Sql(m) => Status::invalid_argument(m.clone()),
            Error::ReadOnly(m) => Status::permission_denied(format!("read-only: {m}")),
            _ => Status::internal(e.to_string()),
        }
    }
}