From fc06f598473c1e5d05642e35ca2f31e8f1970adb Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Fri, 7 Feb 2025 15:54:47 -0500 Subject: [PATCH 1/2] Add docs and examples for `DataFusionErrorBuilder` --- datafusion/common/src/error.rs | 64 ++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/datafusion/common/src/error.rs b/datafusion/common/src/error.rs index 013b1d5a2cab..b23c8d1d54a0 100644 --- a/datafusion/common/src/error.rs +++ b/datafusion/common/src/error.rs @@ -468,6 +468,11 @@ impl DataFusionError { "".to_owned() } + /// Return a [`DataFusionErrorBuilder`] to build a [`DataFusionError`] + pub fn builder() -> DataFusionErrorBuilder { + DataFusionErrorBuilder::default() + } + fn error_prefix(&self) -> &'static str { match self { DataFusionError::ArrowError(_, _) => "Arrow error: ", @@ -602,6 +607,9 @@ impl DataFusionError { DiagnosticsIterator { head: self }.next() } + /// Return an iterator this [`DataFusionError`] and any other + /// [`DataFusionError`]s in a [`DataFusionError::Collection`]. + /// /// Sometimes DataFusion is able to collect multiple errors in a SQL query /// before terminating, e.g. across different expressions in a SELECT /// statements or different sides of a UNION. This method returns an @@ -634,17 +642,65 @@ impl DataFusionError { } } +/// A builder for [`DataFusionError`] +/// +/// This builder can be used to collect multiple errors and return them as a +/// [`DataFusionError::Collection`]. +/// +/// # Example: no errors +/// ``` +/// # use datafusion_common::DataFusionError; +/// let mut builder = DataFusionError::builder(); +/// // ok_or returns the value if no errors have been added +/// assert_eq!(builder.error_or(42).unwrap(), 42); +/// ``` +/// +/// # Example: with errors +/// ``` +/// # use datafusion_common::{assert_contains, DataFusionError}; +/// let mut builder = DataFusionError::builder(); +/// builder.add_error(DataFusionError::Internal("foo".to_owned())); +/// // ok_or returns the value if no errors have been added +/// assert_contains!(builder.error_or(42).unwrap_err().to_string(), "Internal error: foo"); +/// ``` +#[derive(Debug, Default)] pub struct DataFusionErrorBuilder(Vec); impl DataFusionErrorBuilder { + /// Create a new [`DataFusionErrorBuilder`] pub fn new() -> Self { - Self(Vec::new()) + Default::default() } + /// Add an error to the in progress list + /// + /// # Example + /// ``` + /// # use datafusion_common::{assert_contains, DataFusionError}; + /// let mut builder = DataFusionError::builder(); + /// builder.add_error(DataFusionError::Internal("foo".to_owned())); + /// assert_contains!(builder.error_or(42).unwrap_err().to_string(), "Internal error: foo"); + /// ``` pub fn add_error(&mut self, error: DataFusionError) { self.0.push(error); } + /// Add an error to the in progress list, returning the builder + /// + /// # Example + /// ``` + /// # use datafusion_common::{assert_contains, DataFusionError}; + /// let builder = DataFusionError::builder() + /// .with_error(DataFusionError::Internal("foo".to_owned())); + /// assert_contains!(builder.error_or(42).unwrap_err().to_string(), "Internal error: foo"); + /// ``` + pub fn with_error(mut self, error: DataFusionError) -> Self { + self.0.push(error); + self + } + + /// Returns `Ok(ok)` if no errors were added to the builder, + /// otherwise returns a `Result::Err` pub fn error_or(self, ok: T) -> Result { match self.0.len() { 0 => Ok(ok), @@ -654,12 +710,6 @@ impl DataFusionErrorBuilder { } } -impl Default for DataFusionErrorBuilder { - fn default() -> Self { - Self::new() - } -} - /// Unwrap an `Option` if possible. Otherwise return an `DataFusionError::Internal`. /// In normal usage of DataFusion the unwrap should always succeed. /// From 1da42a2b8fd875b664010020e9f20c74b436221f Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Wed, 12 Feb 2025 10:03:22 -0500 Subject: [PATCH 2/2] fix typo --- datafusion/common/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafusion/common/src/error.rs b/datafusion/common/src/error.rs index 1ed9a7ed71c5..c50ec64759d5 100644 --- a/datafusion/common/src/error.rs +++ b/datafusion/common/src/error.rs @@ -621,7 +621,7 @@ impl DataFusionError { DiagnosticsIterator { head: self }.next() } - /// Return an iterator this [`DataFusionError`] and any other + /// Return an iterator over this [`DataFusionError`] and any other /// [`DataFusionError`]s in a [`DataFusionError::Collection`]. /// /// Sometimes DataFusion is able to collect multiple errors in a SQL query