use crate::query_plan_native::native::HResult;
#[derive(Debug)]
pub enum QueryPlanError {
Unexpected {
hresult: u32,
},
Expected {
#[allow(dead_code)]
hresult: u32,
message: String,
},
Deserialization { source: serde_json::Error },
LibraryNotAvailable {
message: String,
},
ConfigContainsNull,
InvalidUtf8 {
message: String,
},
}
impl std::fmt::Display for QueryPlanError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Unexpected { hresult } => {
write!(f, "query plan interop failed with HRESULT 0x{hresult:08X}")
}
Self::Expected { message, .. } => {
write!(f, "query plan error: {message}")
}
Self::Deserialization { source } => {
write!(f, "failed to deserialize query plan: {source}")
}
Self::LibraryNotAvailable { message } => {
write!(f, "native query plan library not available: {message}")
}
Self::ConfigContainsNull => {
write!(f, "configuration string contains interior null character")
}
Self::InvalidUtf8 { message } => {
write!(f, "native library returned invalid UTF-8: {message}")
}
}
}
}
impl std::error::Error for QueryPlanError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Deserialization { source } => Some(source),
_ => None,
}
}
}
impl From<serde_json::Error> for QueryPlanError {
fn from(source: serde_json::Error) -> Self {
Self::Deserialization { source }
}
}
impl QueryPlanError {
pub(crate) fn from_hresult(hr: HResult) -> Self {
Self::Unexpected { hresult: hr as u32 }
}
pub(crate) fn from_hresult_with_payload(hr: HResult, payload: String) -> Self {
Self::Expected {
hresult: hr as u32,
message: payload,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unexpected_error_display() {
let err = QueryPlanError::from_hresult(-2147467259); assert!(format!("{err}").contains("HRESULT"));
}
#[test]
fn expected_error_display() {
let err = QueryPlanError::from_hresult_with_payload(-1, "syntax error".to_string());
let msg = format!("{err}");
assert!(msg.contains("syntax error"));
}
#[test]
fn deserialization_error_from_serde() {
let err: QueryPlanError =
serde_json::from_str::<crate::driver::dataflow::query_plan::QueryPlan>("invalid")
.unwrap_err()
.into();
assert!(matches!(err, QueryPlanError::Deserialization { .. }));
}
#[test]
fn config_null_error() {
let err = QueryPlanError::ConfigContainsNull;
assert!(format!("{err}").contains("null"));
}
}