use snafu::Snafu;
use crate::{DiagnosticSet, WriteBackend};
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Snafu)]
#[non_exhaustive]
pub enum Error {
#[snafu(display("invalid compatibility level {level}"))]
InvalidCompatibilityLevel {
level: u16,
},
#[snafu(display("invalid identifier: {reason}"))]
InvalidIdentifier {
reason: String,
},
#[snafu(display("write planning failed with {} diagnostic(s)", diagnostics.len()))]
Planning {
diagnostics: DiagnosticSet,
},
#[snafu(display(
"value conversion failed with {} diagnostic(s)",
diagnostics.len()
))]
ValueConversion {
diagnostics: DiagnosticSet,
},
#[snafu(display(
"direct encoding failed with {} diagnostic(s)",
diagnostics.len()
))]
DirectEncoding {
diagnostics: DiagnosticSet,
},
#[snafu(display("write backend {backend:?} is unavailable: {reason}"))]
BackendUnavailable {
backend: WriteBackend,
reason: String,
},
#[snafu(display("tiberius operation failed: {source}"))]
Tiberius {
source: tiberius::error::Error,
},
}
#[cfg(test)]
mod tests {
use std::{borrow::Cow, error::Error as StdError};
use crate::{Diagnostic, DiagnosticCode, DiagnosticSet, Error};
#[test]
fn planning_error_display_includes_diagnostic_count() {
let diagnostics = DiagnosticSet::from(vec![Diagnostic::error(
DiagnosticCode::UnsupportedArrowType,
"unsupported",
)]);
let err = Error::Planning { diagnostics };
assert_eq!(
err.to_string(),
"write planning failed with 1 diagnostic(s)"
);
}
#[test]
fn value_conversion_error_display_includes_diagnostic_count() {
let diagnostics = DiagnosticSet::from(vec![Diagnostic::error(
DiagnosticCode::ValueConversionUnsupported,
"unsupported conversion",
)]);
let err = Error::ValueConversion { diagnostics };
assert_eq!(
err.to_string(),
"value conversion failed with 1 diagnostic(s)"
);
}
#[test]
fn direct_encoding_error_display_includes_diagnostic_count() {
let diagnostics = DiagnosticSet::from(vec![Diagnostic::error(
DiagnosticCode::DirectEncodingInvalidPayload,
"invalid payload",
)]);
let err = Error::DirectEncoding { diagnostics };
assert_eq!(
err.to_string(),
"direct encoding failed with 1 diagnostic(s)"
);
}
#[test]
fn backend_unavailable_error_display_includes_backend() {
let err = Error::BackendUnavailable {
backend: crate::WriteBackend::DirectRawBulk,
reason: "not implemented".to_owned(),
};
assert_eq!(
err.to_string(),
"write backend DirectRawBulk is unavailable: not implemented"
);
}
#[test]
fn tiberius_error_display_includes_source_error() {
let err = Error::Tiberius {
source: tiberius::error::Error::Protocol(Cow::Borrowed("invalid token")),
};
assert_eq!(
err.to_string(),
"tiberius operation failed: Protocol error: invalid token"
);
}
#[test]
fn tiberius_error_preserves_source_error() {
let err = Error::Tiberius {
source: tiberius::error::Error::BulkInput(Cow::Borrowed("row payload is malformed")),
};
let source = StdError::source(&err).expect("tiberius source should be preserved");
assert_eq!(
source.to_string(),
"BULK UPLOAD input failure: row payload is malformed"
);
}
}