diff --git a/Cargo.toml b/Cargo.toml
index e947afff8f4fc..fa0ce2461fafa 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -52,6 +52,8 @@ members = [
     "datafusion-examples/examples/ffi/ffi_module_loader",
     "test-utils",
     "benchmarks",
+    "datafusion/macros",
+    "datafusion/doc",
 ]
 resolver = "2"
 
@@ -100,6 +102,7 @@ datafusion = { path = "datafusion/core", version = "43.0.0", default-features =
 datafusion-catalog = { path = "datafusion/catalog", version = "43.0.0" }
 datafusion-common = { path = "datafusion/common", version = "43.0.0", default-features = false }
 datafusion-common-runtime = { path = "datafusion/common-runtime", version = "43.0.0" }
+datafusion-doc = { path = "datafusion/doc", version = "43.0.0" }
 datafusion-execution = { path = "datafusion/execution", version = "43.0.0" }
 datafusion-expr = { path = "datafusion/expr", version = "43.0.0" }
 datafusion-expr-common = { path = "datafusion/expr-common", version = "43.0.0" }
@@ -110,6 +113,7 @@ datafusion-functions-aggregate-common = { path = "datafusion/functions-aggregate
 datafusion-functions-nested = { path = "datafusion/functions-nested", version = "43.0.0" }
 datafusion-functions-window = { path = "datafusion/functions-window", version = "43.0.0" }
 datafusion-functions-window-common = { path = "datafusion/functions-window-common", version = "43.0.0" }
+datafusion-macros = { path = "datafusion/macros", version = "43.0.0" }
 datafusion-optimizer = { path = "datafusion/optimizer", version = "43.0.0", default-features = false }
 datafusion-physical-expr = { path = "datafusion/physical-expr", version = "43.0.0", default-features = false }
 datafusion-physical-expr-common = { path = "datafusion/physical-expr-common", version = "43.0.0", default-features = false }
diff --git a/datafusion-cli/Cargo.lock b/datafusion-cli/Cargo.lock
index 8afb096df55f1..fdab12579100a 100644
--- a/datafusion-cli/Cargo.lock
+++ b/datafusion-cli/Cargo.lock
@@ -1319,6 +1319,10 @@ dependencies = [
  "tokio",
 ]
 
+[[package]]
+name = "datafusion-doc"
+version = "43.0.0"
+
 [[package]]
 name = "datafusion-execution"
 version = "43.0.0"
@@ -1348,6 +1352,7 @@ dependencies = [
  "arrow-buffer",
  "chrono",
  "datafusion-common",
+ "datafusion-doc",
  "datafusion-expr-common",
  "datafusion-functions-aggregate-common",
  "datafusion-functions-window-common",
@@ -1382,8 +1387,10 @@ dependencies = [
  "blake3",
  "chrono",
  "datafusion-common",
+ "datafusion-doc",
  "datafusion-execution",
  "datafusion-expr",
+ "datafusion-macros",
  "hashbrown 0.14.5",
  "hex",
  "itertools",
@@ -1469,6 +1476,16 @@ dependencies = [
  "datafusion-physical-expr-common",
 ]
 
+[[package]]
+name = "datafusion-macros"
+version = "43.0.0"
+dependencies = [
+ "datafusion-doc",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "datafusion-optimizer"
 version = "43.0.0"
diff --git a/datafusion/doc/Cargo.toml b/datafusion/doc/Cargo.toml
new file mode 100644
index 0000000000000..c188bcb2a5352
--- /dev/null
+++ b/datafusion/doc/Cargo.toml
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[package]
+name = "datafusion-doc"
+description = "Documentation module for DataFusion query engine"
+keywords = ["datafusion", "query", "sql"]
+version = { workspace = true }
+edition = { workspace = true }
+homepage = { workspace = true }
+repository = { workspace = true }
+license = { workspace = true }
+authors = { workspace = true }
+rust-version = { workspace = true }
+
+[lints]
+workspace = true
+
+[lib]
+name = "datafusion_doc"
+path = "src/lib.rs"
diff --git a/datafusion/expr/src/udf_docs.rs b/datafusion/doc/src/lib.rs
similarity index 86%
rename from datafusion/expr/src/udf_docs.rs
rename to datafusion/doc/src/lib.rs
index a124361e42a3d..c4b0cbbae498e 100644
--- a/datafusion/expr/src/udf_docs.rs
+++ b/datafusion/doc/src/lib.rs
@@ -15,15 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use datafusion_common::exec_err;
-use datafusion_common::Result;
-
-/// Documentation for use by [`ScalarUDFImpl`](crate::ScalarUDFImpl),
-/// [`AggregateUDFImpl`](crate::AggregateUDFImpl) and [`WindowUDFImpl`](crate::WindowUDFImpl) functions
+#[allow(rustdoc::broken_intra_doc_links)]
+/// Documentation for use by [`ScalarUDFImpl`](ScalarUDFImpl),
+/// [`AggregateUDFImpl`](AggregateUDFImpl) and [`WindowUDFImpl`](WindowUDFImpl) functions
 /// that will be used to generate public documentation.
 ///
-/// The name of the udf will be pulled from the [`ScalarUDFImpl::name`](crate::ScalarUDFImpl::name),
-/// [`AggregateUDFImpl::name`](crate::AggregateUDFImpl::name) or [`WindowUDFImpl::name`](crate::WindowUDFImpl::name)
+/// The name of the udf will be pulled from the [`ScalarUDFImpl::name`](ScalarUDFImpl::name),
+/// [`AggregateUDFImpl::name`](AggregateUDFImpl::name) or [`WindowUDFImpl::name`](WindowUDFImpl::name)
 /// function as appropriate.
 ///
 /// All strings in the documentation are required to be
@@ -79,18 +77,21 @@ pub struct DocSection {
 /// Example:
 ///
 /// ```rust
-/// # use datafusion_expr::Documentation;
-/// # use datafusion_expr::scalar_doc_sections::DOC_SECTION_MATH;
-/// # use datafusion_common::Result;
-/// #
-/// # fn main() -> Result<()> {
-///       let documentation = Documentation::builder()
-///           .with_doc_section(DOC_SECTION_MATH)
+///
+/// # fn main() {
+///     use datafusion_doc::{DocSection, Documentation};
+///     let doc_section = DocSection {
+///         include: true,
+///         label: "Display Label",
+///         description: None,
+///     };
+///
+///     let documentation = Documentation::builder()
+///           .with_doc_section(doc_section)
 ///           .with_description("Add one to an int32")
 ///           .with_syntax_example("add_one(2)")
 ///           .with_argument("arg_1", "The int32 number to add one to")
-///           .build()?;
-///       Ok(())  
+///           .build();
 /// # }
 pub struct DocumentationBuilder {
     pub doc_section: Option<DocSection>,
@@ -190,7 +191,10 @@ impl DocumentationBuilder {
         self
     }
 
-    pub fn build(self) -> Result<Documentation> {
+    /// Build the documentation from provided components
+    ///
+    /// Panics if `doc_section`, `description` or `syntax_example` is not set
+    pub fn build(self) -> Documentation {
         let Self {
             doc_section,
             description,
@@ -202,16 +206,16 @@ impl DocumentationBuilder {
         } = self;
 
         if doc_section.is_none() {
-            return exec_err!("Documentation must have a doc section");
+            panic!("Documentation must have a doc section");
         }
         if description.is_none() {
-            return exec_err!("Documentation must have a description");
+            panic!("Documentation must have a description");
         }
         if syntax_example.is_none() {
-            return exec_err!("Documentation must have a syntax_example");
+            panic!("Documentation must have a syntax_example");
         }
 
-        Ok(Documentation {
+        Documentation {
             doc_section: doc_section.unwrap(),
             description: description.unwrap(),
             syntax_example: syntax_example.unwrap(),
@@ -219,7 +223,7 @@ impl DocumentationBuilder {
             arguments,
             alternative_syntax,
             related_udfs,
-        })
+        }
     }
 }
 
diff --git a/datafusion/expr/Cargo.toml b/datafusion/expr/Cargo.toml
index 19cd5ed3158b4..438662e0642b0 100644
--- a/datafusion/expr/Cargo.toml
+++ b/datafusion/expr/Cargo.toml
@@ -44,6 +44,7 @@ arrow-array = { workspace = true }
 arrow-buffer = { workspace = true }
 chrono = { workspace = true }
 datafusion-common = { workspace = true }
+datafusion-doc = { workspace = true }
 datafusion-expr-common = { workspace = true }
 datafusion-functions-aggregate-common = { workspace = true }
 datafusion-functions-window-common = { workspace = true }
diff --git a/datafusion/expr/src/lib.rs b/datafusion/expr/src/lib.rs
index d8b829f27e7d4..c5016a18d4438 100644
--- a/datafusion/expr/src/lib.rs
+++ b/datafusion/expr/src/lib.rs
@@ -34,7 +34,6 @@ mod partition_evaluator;
 mod table_source;
 mod udaf;
 mod udf;
-mod udf_docs;
 mod udwf;
 
 pub mod conditional_expressions;
@@ -66,6 +65,7 @@ pub mod var_provider;
 pub mod window_frame;
 pub mod window_state;
 
+pub use datafusion_doc::{DocSection, Documentation, DocumentationBuilder};
 pub use datafusion_expr_common::accumulator::Accumulator;
 pub use datafusion_expr_common::columnar_value::ColumnarValue;
 pub use datafusion_expr_common::groups_accumulator::{EmitTo, GroupsAccumulator};
@@ -93,7 +93,6 @@ pub use udaf::{
     aggregate_doc_sections, AggregateUDF, AggregateUDFImpl, ReversedUDAF, StatisticsArgs,
 };
 pub use udf::{scalar_doc_sections, ScalarFunctionArgs, ScalarUDF, ScalarUDFImpl};
-pub use udf_docs::{DocSection, Documentation, DocumentationBuilder};
 pub use udwf::{window_doc_sections, ReversedUDWF, WindowUDF, WindowUDFImpl};
 pub use window_frame::{WindowFrame, WindowFrameBound, WindowFrameUnits};
 
diff --git a/datafusion/expr/src/udaf.rs b/datafusion/expr/src/udaf.rs
index dbbf88447ba39..28506caceea28 100644
--- a/datafusion/expr/src/udaf.rs
+++ b/datafusion/expr/src/udaf.rs
@@ -339,7 +339,6 @@ where
 ///             .with_syntax_example("geo_mean(2.0)")
 ///             .with_argument("arg1", "The Float64 number for the geometric mean")
 ///             .build()
-///             .unwrap()
 ///     })
 /// }
 ///    
diff --git a/datafusion/expr/src/udf.rs b/datafusion/expr/src/udf.rs
index 57b8d9c6b02e8..9a588cf43be67 100644
--- a/datafusion/expr/src/udf.rs
+++ b/datafusion/expr/src/udf.rs
@@ -382,7 +382,6 @@ pub struct ScalarFunctionArgs<'a> {
 ///             .with_syntax_example("add_one(2)")
 ///             .with_argument("arg1", "The int32 number to add one to")
 ///             .build()
-///             .unwrap()
 ///     })
 /// }
 ///
diff --git a/datafusion/expr/src/udwf.rs b/datafusion/expr/src/udwf.rs
index 475b864a8a18d..11bc7043da761 100644
--- a/datafusion/expr/src/udwf.rs
+++ b/datafusion/expr/src/udwf.rs
@@ -30,10 +30,10 @@ use arrow::datatypes::{DataType, Field};
 
 use crate::expr::WindowFunction;
 use crate::{
-    function::WindowFunctionSimplification, Documentation, Expr, PartitionEvaluator,
-    Signature,
+    function::WindowFunctionSimplification, Expr, PartitionEvaluator, Signature,
 };
 use datafusion_common::{not_impl_err, Result};
+use datafusion_doc::Documentation;
 use datafusion_functions_window_common::expr::ExpressionArgs;
 use datafusion_functions_window_common::field::WindowUDFFieldArgs;
 use datafusion_functions_window_common::partition::PartitionEvaluatorArgs;
@@ -264,7 +264,6 @@ where
 ///             .with_syntax_example("smooth_it(2)")
 ///             .with_argument("arg1", "The int32 number to smooth by")
 ///             .build()
-///             .unwrap()
 ///     })
 /// }
 ///
@@ -557,7 +556,7 @@ impl WindowUDFImpl for AliasedWindowUDFImpl {
 
 // Window UDF doc sections for use in public documentation
 pub mod window_doc_sections {
-    use crate::DocSection;
+    use datafusion_doc::DocSection;
 
     pub fn doc_sections() -> Vec<DocSection> {
         vec![
diff --git a/datafusion/functions-aggregate/src/approx_distinct.rs b/datafusion/functions-aggregate/src/approx_distinct.rs
index 1df106feb4d38..ef7b12768b75a 100644
--- a/datafusion/functions-aggregate/src/approx_distinct.rs
+++ b/datafusion/functions-aggregate/src/approx_distinct.rs
@@ -334,6 +334,5 @@ fn get_approx_distinct_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions-aggregate/src/approx_median.rs b/datafusion/functions-aggregate/src/approx_median.rs
index 96609622a51e4..3a33e725ec0a0 100644
--- a/datafusion/functions-aggregate/src/approx_median.rs
+++ b/datafusion/functions-aggregate/src/approx_median.rs
@@ -147,6 +147,5 @@ fn get_approx_median_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions-aggregate/src/approx_percentile_cont.rs b/datafusion/functions-aggregate/src/approx_percentile_cont.rs
index 53fcfd641ddfc..8bc52f9a1bd06 100644
--- a/datafusion/functions-aggregate/src/approx_percentile_cont.rs
+++ b/datafusion/functions-aggregate/src/approx_percentile_cont.rs
@@ -298,7 +298,6 @@ fn get_approx_percentile_cont_doc() -> &'static Documentation {
             .with_argument("percentile", "Percentile to compute. Must be a float value between 0 and 1 (inclusive).")
             .with_argument("centroids", "Number of centroids to use in the t-digest algorithm. _Default is 100_. A higher number results in more accurate approximation but requires more memory.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/approx_percentile_cont_with_weight.rs b/datafusion/functions-aggregate/src/approx_percentile_cont_with_weight.rs
index 5458d0f792b92..a309ff48ca539 100644
--- a/datafusion/functions-aggregate/src/approx_percentile_cont_with_weight.rs
+++ b/datafusion/functions-aggregate/src/approx_percentile_cont_with_weight.rs
@@ -184,7 +184,6 @@ fn get_approx_percentile_cont_with_weight_doc() -> &'static Documentation {
             .with_argument("weight", "Expression to use as weight. Can be a constant, column, or function, and any combination of arithmetic operators.")
             .with_argument("percentile", "Percentile to compute. Must be a float value between 0 and 1 (inclusive).")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/array_agg.rs b/datafusion/functions-aggregate/src/array_agg.rs
index 252a07cb11d80..dc57782ac2f3f 100644
--- a/datafusion/functions-aggregate/src/array_agg.rs
+++ b/datafusion/functions-aggregate/src/array_agg.rs
@@ -171,7 +171,6 @@ fn get_array_agg_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/average.rs b/datafusion/functions-aggregate/src/average.rs
index 710b7e69ac5c3..12d98a041fb11 100644
--- a/datafusion/functions-aggregate/src/average.rs
+++ b/datafusion/functions-aggregate/src/average.rs
@@ -266,7 +266,6 @@ fn get_avg_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/bit_and_or_xor.rs b/datafusion/functions-aggregate/src/bit_and_or_xor.rs
index 249ff02e72221..8b5da2e3b1628 100644
--- a/datafusion/functions-aggregate/src/bit_and_or_xor.rs
+++ b/datafusion/functions-aggregate/src/bit_and_or_xor.rs
@@ -145,7 +145,6 @@ fn get_bit_and_doc() -> &'static Documentation {
             .with_syntax_example("bit_and(expression)")
             .with_standard_argument("expression", Some("Integer"))
             .build()
-            .unwrap()
     })
 }
 
@@ -159,7 +158,6 @@ fn get_bit_or_doc() -> &'static Documentation {
             .with_syntax_example("bit_or(expression)")
             .with_standard_argument("expression", Some("Integer"))
             .build()
-            .unwrap()
     })
 }
 
@@ -175,7 +173,6 @@ fn get_bit_xor_doc() -> &'static Documentation {
             .with_syntax_example("bit_xor(expression)")
             .with_standard_argument("expression", Some("Integer"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/bool_and_or.rs b/datafusion/functions-aggregate/src/bool_and_or.rs
index 87293ccfa21f5..55f5aa988495f 100644
--- a/datafusion/functions-aggregate/src/bool_and_or.rs
+++ b/datafusion/functions-aggregate/src/bool_and_or.rs
@@ -204,7 +204,6 @@ fn get_bool_and_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
@@ -353,7 +352,6 @@ fn get_bool_or_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/correlation.rs b/datafusion/functions-aggregate/src/correlation.rs
index 187a43ecbea3c..14124ce46aea9 100644
--- a/datafusion/functions-aggregate/src/correlation.rs
+++ b/datafusion/functions-aggregate/src/correlation.rs
@@ -138,7 +138,6 @@ fn get_corr_doc() -> &'static Documentation {
             .with_standard_argument("expression1", Some("First"))
             .with_standard_argument("expression2", Some("Second"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/count.rs b/datafusion/functions-aggregate/src/count.rs
index 8fdd702b5b7c6..4b1ab323b8f44 100644
--- a/datafusion/functions-aggregate/src/count.rs
+++ b/datafusion/functions-aggregate/src/count.rs
@@ -359,7 +359,6 @@ fn get_count_doc() -> &'static Documentation {
 ```"#)
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/covariance.rs b/datafusion/functions-aggregate/src/covariance.rs
index 063aaa92059dd..94727fddd9f8b 100644
--- a/datafusion/functions-aggregate/src/covariance.rs
+++ b/datafusion/functions-aggregate/src/covariance.rs
@@ -154,7 +154,6 @@ fn get_covar_samp_doc() -> &'static Documentation {
             .with_standard_argument("expression1", Some("First"))
             .with_standard_argument("expression2", Some("Second"))
             .build()
-            .unwrap()
     })
 }
 
@@ -252,7 +251,6 @@ fn get_covar_pop_doc() -> &'static Documentation {
             .with_standard_argument("expression1", Some("First"))
             .with_standard_argument("expression2", Some("Second"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/first_last.rs b/datafusion/functions-aggregate/src/first_last.rs
index 493c2cde2be82..a20330a7aaf59 100644
--- a/datafusion/functions-aggregate/src/first_last.rs
+++ b/datafusion/functions-aggregate/src/first_last.rs
@@ -186,7 +186,6 @@ fn get_first_value_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
@@ -508,7 +507,6 @@ fn get_last_value_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/grouping.rs b/datafusion/functions-aggregate/src/grouping.rs
index 27949aa3df277..88275193d7732 100644
--- a/datafusion/functions-aggregate/src/grouping.rs
+++ b/datafusion/functions-aggregate/src/grouping.rs
@@ -129,6 +129,5 @@ fn get_grouping_doc() -> &'static Documentation {
             )
             .with_argument("expression", "Expression to evaluate whether data is aggregated across the specified column. Can be a constant, column, or function.")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions-aggregate/src/median.rs b/datafusion/functions-aggregate/src/median.rs
index a7114bb68bfda..7e0b52a2f8579 100644
--- a/datafusion/functions-aggregate/src/median.rs
+++ b/datafusion/functions-aggregate/src/median.rs
@@ -179,7 +179,6 @@ fn get_median_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/min_max.rs b/datafusion/functions-aggregate/src/min_max.rs
index 618edd343f7d8..49b528c2f41c4 100644
--- a/datafusion/functions-aggregate/src/min_max.rs
+++ b/datafusion/functions-aggregate/src/min_max.rs
@@ -370,7 +370,6 @@ fn get_max_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
@@ -1200,7 +1199,6 @@ fn get_min_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/nth_value.rs b/datafusion/functions-aggregate/src/nth_value.rs
index f3e892fa73d85..8a8010ef27bd8 100644
--- a/datafusion/functions-aggregate/src/nth_value.rs
+++ b/datafusion/functions-aggregate/src/nth_value.rs
@@ -195,7 +195,6 @@ fn get_nth_value_doc() -> &'static Documentation {
             .with_argument("expression", "The column or expression to retrieve the nth value from.")
             .with_argument("n", "The position (nth) of the value to retrieve, based on the ordering.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/regr.rs b/datafusion/functions-aggregate/src/regr.rs
index 9dd13634ff2d6..dca309dfe101d 100644
--- a/datafusion/functions-aggregate/src/regr.rs
+++ b/datafusion/functions-aggregate/src/regr.rs
@@ -148,7 +148,6 @@ fn get_regr_docs() -> &'static HashMap<RegrType, Documentation> {
                 .with_standard_argument("expression_y", Some("Dependent variable"))
                 .with_standard_argument("expression_x", Some("Independent variable"))
                 .build()
-                .unwrap()
         );
 
         hash_map.insert(
@@ -163,7 +162,6 @@ fn get_regr_docs() -> &'static HashMap<RegrType, Documentation> {
                 .with_standard_argument("expression_y", Some("Dependent variable"))
                 .with_standard_argument("expression_x", Some("Independent variable"))
                 .build()
-                .unwrap()
         );
 
         hash_map.insert(
@@ -177,7 +175,6 @@ fn get_regr_docs() -> &'static HashMap<RegrType, Documentation> {
                 .with_standard_argument("expression_y", Some("Dependent variable"))
                 .with_standard_argument("expression_x", Some("Independent variable"))
                 .build()
-                .unwrap()
         );
 
         hash_map.insert(
@@ -191,7 +188,6 @@ fn get_regr_docs() -> &'static HashMap<RegrType, Documentation> {
                 .with_standard_argument("expression_y", Some("Dependent variable"))
                 .with_standard_argument("expression_x", Some("Independent variable"))
                 .build()
-                .unwrap()
         );
 
         hash_map.insert(
@@ -205,7 +201,6 @@ fn get_regr_docs() -> &'static HashMap<RegrType, Documentation> {
                 .with_standard_argument("expression_y", Some("Dependent variable"))
                 .with_standard_argument("expression_x", Some("Independent variable"))
                 .build()
-                .unwrap()
         );
 
         hash_map.insert(
@@ -219,7 +214,6 @@ fn get_regr_docs() -> &'static HashMap<RegrType, Documentation> {
                 .with_standard_argument("expression_y", Some("Dependent variable"))
                 .with_standard_argument("expression_x", Some("Independent variable"))
                 .build()
-                .unwrap()
         );
 
         hash_map.insert(
@@ -233,7 +227,6 @@ fn get_regr_docs() -> &'static HashMap<RegrType, Documentation> {
                 .with_standard_argument("expression_y", Some("Dependent variable"))
                 .with_standard_argument("expression_x", Some("Independent variable"))
                 .build()
-                .unwrap()
         );
 
         hash_map.insert(
@@ -247,7 +240,6 @@ fn get_regr_docs() -> &'static HashMap<RegrType, Documentation> {
                 .with_standard_argument("expression_y", Some("Dependent variable"))
                 .with_standard_argument("expression_x", Some("Independent variable"))
                 .build()
-                .unwrap()
         );
 
         hash_map.insert(
@@ -261,7 +253,6 @@ fn get_regr_docs() -> &'static HashMap<RegrType, Documentation> {
                 .with_standard_argument("expression_y", Some("Dependent variable"))
                 .with_standard_argument("expression_x", Some("Independent variable"))
                 .build()
-                .unwrap()
         );
         hash_map
     })
diff --git a/datafusion/functions-aggregate/src/stddev.rs b/datafusion/functions-aggregate/src/stddev.rs
index d1f43c6661383..3e1038f8ce286 100644
--- a/datafusion/functions-aggregate/src/stddev.rs
+++ b/datafusion/functions-aggregate/src/stddev.rs
@@ -158,7 +158,6 @@ fn get_stddev_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
@@ -282,7 +281,6 @@ fn get_stddev_pop_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/string_agg.rs b/datafusion/functions-aggregate/src/string_agg.rs
index 68267b9f72c7d..18cf6a15988d6 100644
--- a/datafusion/functions-aggregate/src/string_agg.rs
+++ b/datafusion/functions-aggregate/src/string_agg.rs
@@ -130,7 +130,6 @@ fn get_string_agg_doc() -> &'static Documentation {
             .with_argument("expression", "The string expression to concatenate. Can be a column or any valid string expression.")
             .with_argument("delimiter", "A literal string used as a separator between the concatenated values.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/sum.rs b/datafusion/functions-aggregate/src/sum.rs
index 6ad376db4fb9c..6c438e10ea662 100644
--- a/datafusion/functions-aggregate/src/sum.rs
+++ b/datafusion/functions-aggregate/src/sum.rs
@@ -263,7 +263,6 @@ fn get_sum_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", None)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-aggregate/src/variance.rs b/datafusion/functions-aggregate/src/variance.rs
index 55d4181a96dfe..bb518bf76b6a0 100644
--- a/datafusion/functions-aggregate/src/variance.rs
+++ b/datafusion/functions-aggregate/src/variance.rs
@@ -153,7 +153,6 @@ fn get_variance_sample_doc() -> &'static Documentation {
             .with_syntax_example("var(expression)")
             .with_standard_argument("expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -259,7 +258,6 @@ fn get_variance_population_doc() -> &'static Documentation {
             .with_syntax_example("var_pop(expression)")
             .with_standard_argument("expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/array_has.rs b/datafusion/functions-nested/src/array_has.rs
index fe1d05199e80d..cd45137f52f8a 100644
--- a/datafusion/functions-nested/src/array_has.rs
+++ b/datafusion/functions-nested/src/array_has.rs
@@ -167,7 +167,6 @@ fn get_array_has_doc() -> &'static Documentation {
                 "Scalar or Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -362,7 +361,6 @@ fn get_array_has_all_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -443,7 +441,6 @@ fn get_array_has_any_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/cardinality.rs b/datafusion/functions-nested/src/cardinality.rs
index b6661e0807f4e..74efe75622889 100644
--- a/datafusion/functions-nested/src/cardinality.rs
+++ b/datafusion/functions-nested/src/cardinality.rs
@@ -121,7 +121,6 @@ fn get_cardinality_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/concat.rs b/datafusion/functions-nested/src/concat.rs
index 4aa6bb5da9b24..94ccfef1b2d72 100644
--- a/datafusion/functions-nested/src/concat.rs
+++ b/datafusion/functions-nested/src/concat.rs
@@ -128,7 +128,6 @@ fn get_array_append_doc() -> &'static Documentation {
                 "Element to append to the array.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -224,7 +223,6 @@ fn get_array_prepend_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -342,7 +340,6 @@ fn get_array_concat_doc() -> &'static Documentation {
                 "Subsequent array column or literal array to concatenate.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/dimension.rs b/datafusion/functions-nested/src/dimension.rs
index 7df0ed2b40bdb..ec4782521dad0 100644
--- a/datafusion/functions-nested/src/dimension.rs
+++ b/datafusion/functions-nested/src/dimension.rs
@@ -119,7 +119,6 @@ fn get_array_dims_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -206,7 +205,6 @@ fn get_array_ndims_doc() -> &'static Documentation {
                 "Array element.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/distance.rs b/datafusion/functions-nested/src/distance.rs
index 4f890e4166e9f..80c4f0995c988 100644
--- a/datafusion/functions-nested/src/distance.rs
+++ b/datafusion/functions-nested/src/distance.rs
@@ -138,7 +138,6 @@ fn get_array_distance_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/empty.rs b/datafusion/functions-nested/src/empty.rs
index 5d310eb23952e..669d84c2f43d7 100644
--- a/datafusion/functions-nested/src/empty.rs
+++ b/datafusion/functions-nested/src/empty.rs
@@ -111,7 +111,6 @@ fn get_empty_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/except.rs b/datafusion/functions-nested/src/except.rs
index 100fb587d6422..aab2d5896000e 100644
--- a/datafusion/functions-nested/src/except.rs
+++ b/datafusion/functions-nested/src/except.rs
@@ -121,7 +121,6 @@ fn get_array_except_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/extract.rs b/datafusion/functions-nested/src/extract.rs
index 275095832edb9..6b51d1d9b4962 100644
--- a/datafusion/functions-nested/src/extract.rs
+++ b/datafusion/functions-nested/src/extract.rs
@@ -185,7 +185,6 @@ fn get_array_element_doc() -> &'static Documentation {
                 "Index to extract the element from the array.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -395,7 +394,6 @@ fn get_array_slice_doc() -> &'static Documentation {
                 "Stride of the array slice. The default is 1.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -692,7 +690,6 @@ fn get_array_pop_front_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -798,7 +795,6 @@ fn get_array_pop_back_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -912,7 +908,6 @@ fn get_array_any_value_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/flatten.rs b/datafusion/functions-nested/src/flatten.rs
index 4fe631517b09d..98a110de8d2fa 100644
--- a/datafusion/functions-nested/src/flatten.rs
+++ b/datafusion/functions-nested/src/flatten.rs
@@ -128,7 +128,6 @@ fn get_flatten_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/length.rs b/datafusion/functions-nested/src/length.rs
index 3e039f286421a..cb6e545fca778 100644
--- a/datafusion/functions-nested/src/length.rs
+++ b/datafusion/functions-nested/src/length.rs
@@ -119,7 +119,6 @@ fn get_array_length_doc() -> &'static Documentation {
                 "Array dimension.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/make_array.rs b/datafusion/functions-nested/src/make_array.rs
index c84b6f010968c..a98b88b065c59 100644
--- a/datafusion/functions-nested/src/make_array.rs
+++ b/datafusion/functions-nested/src/make_array.rs
@@ -168,7 +168,6 @@ fn get_make_array_doc() -> &'static Documentation {
                 "Expression to include in the output array. Can be a constant, column, or function, and any combination of arithmetic or string operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/map.rs b/datafusion/functions-nested/src/map.rs
index 1211945a8b9db..9f6a5031ac4e6 100644
--- a/datafusion/functions-nested/src/map.rs
+++ b/datafusion/functions-nested/src/map.rs
@@ -301,7 +301,6 @@ SELECT MAKE_MAP(['key1', 'key2'], ['value1', null]);
                         For `make_map`: The list of values to be mapped to the corresponding keys."
                     )
                     .build()
-                    .unwrap()
             })
 }
 
diff --git a/datafusion/functions-nested/src/map_extract.rs b/datafusion/functions-nested/src/map_extract.rs
index d2bb6595fe76e..8888ed03f94a9 100644
--- a/datafusion/functions-nested/src/map_extract.rs
+++ b/datafusion/functions-nested/src/map_extract.rs
@@ -144,7 +144,6 @@ SELECT map_extract(MAP {'x': 10, 'y': NULL, 'z': 30}, 'y');
                 "Key to extract from the map. Can be a constant, column, or function, any combination of arithmetic or string operators, or a named expression of the previously listed.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/map_keys.rs b/datafusion/functions-nested/src/map_keys.rs
index 03e381e372f64..11b03bf72e44d 100644
--- a/datafusion/functions-nested/src/map_keys.rs
+++ b/datafusion/functions-nested/src/map_keys.rs
@@ -114,7 +114,6 @@ SELECT map_keys(map([100, 5], [42, 43]));
                 "Map expression. Can be a constant, column, or function, and any combination of map operators."
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/map_values.rs b/datafusion/functions-nested/src/map_values.rs
index dc7d9c9db8eec..729dc008f29a7 100644
--- a/datafusion/functions-nested/src/map_values.rs
+++ b/datafusion/functions-nested/src/map_values.rs
@@ -114,7 +114,6 @@ SELECT map_values(map([100, 5], [42, 43]));
                 "Map expression. Can be a constant, column, or function, and any combination of map operators."
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/position.rs b/datafusion/functions-nested/src/position.rs
index adb45141601d6..a4fce2644a6be 100644
--- a/datafusion/functions-nested/src/position.rs
+++ b/datafusion/functions-nested/src/position.rs
@@ -134,7 +134,6 @@ fn get_array_position_doc() -> &'static Documentation {
                 "Index at which to start searching.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -293,7 +292,6 @@ fn get_array_positions_doc() -> &'static Documentation {
                 "Element to search for positions in the array.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/range.rs b/datafusion/functions-nested/src/range.rs
index ddc56b1e4ee88..9355050cf0c9c 100644
--- a/datafusion/functions-nested/src/range.rs
+++ b/datafusion/functions-nested/src/range.rs
@@ -182,7 +182,6 @@ fn get_range_doc() -> &'static Documentation {
                 "Increase by step (cannot be 0). Steps less than a day are supported only for timestamp ranges.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -316,7 +315,6 @@ fn get_generate_series_doc() -> &'static Documentation {
                 "increase by step (can not be 0). Steps less than a day are supported only for timestamp ranges.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/remove.rs b/datafusion/functions-nested/src/remove.rs
index dc1ed4833c67c..c7797990fddd8 100644
--- a/datafusion/functions-nested/src/remove.rs
+++ b/datafusion/functions-nested/src/remove.rs
@@ -116,7 +116,6 @@ fn get_array_remove_doc() -> &'static Documentation {
                 "Element to be removed from the array.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -204,7 +203,6 @@ fn get_array_remove_n_doc() -> &'static Documentation {
                 "Number of first occurrences to remove.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -288,7 +286,6 @@ fn get_array_remove_all_doc() -> &'static Documentation {
                 "Element to be removed from the array.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/repeat.rs b/datafusion/functions-nested/src/repeat.rs
index 55584c143a549..4bf008fef6726 100644
--- a/datafusion/functions-nested/src/repeat.rs
+++ b/datafusion/functions-nested/src/repeat.rs
@@ -127,7 +127,6 @@ fn get_array_repeat_doc() -> &'static Documentation {
                 "Value of how many times to repeat the element.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/replace.rs b/datafusion/functions-nested/src/replace.rs
index 1d0a1d1f28152..4388e54bc67ab 100644
--- a/datafusion/functions-nested/src/replace.rs
+++ b/datafusion/functions-nested/src/replace.rs
@@ -136,7 +136,6 @@ fn get_array_replace_doc() -> &'static Documentation {
                 "Final element.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -220,7 +219,6 @@ fn get_array_replace_n_doc() -> &'static Documentation {
                 "Number of first occurrences to replace.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -300,7 +298,6 @@ fn get_array_replace_all_doc() -> &'static Documentation {
                 "Final element.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/resize.rs b/datafusion/functions-nested/src/resize.rs
index b0255e7be2a32..31f4aa7ca3c57 100644
--- a/datafusion/functions-nested/src/resize.rs
+++ b/datafusion/functions-nested/src/resize.rs
@@ -126,7 +126,6 @@ fn get_array_resize_doc() -> &'static Documentation {
                 "Defines new elements' value or empty if value is not set.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/reverse.rs b/datafusion/functions-nested/src/reverse.rs
index 1ecf7f8484684..a4ccf6a0eed69 100644
--- a/datafusion/functions-nested/src/reverse.rs
+++ b/datafusion/functions-nested/src/reverse.rs
@@ -110,7 +110,6 @@ fn get_array_reverse_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/set_ops.rs b/datafusion/functions-nested/src/set_ops.rs
index ce8d248319fe5..4a5375c4b815d 100644
--- a/datafusion/functions-nested/src/set_ops.rs
+++ b/datafusion/functions-nested/src/set_ops.rs
@@ -146,7 +146,6 @@ fn get_array_union_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -232,7 +231,6 @@ fn get_array_intersect_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -318,7 +316,6 @@ fn get_array_distinct_doc() -> &'static Documentation {
                 "Array expression. Can be a constant, column, or function, and any combination of array operators.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/sort.rs b/datafusion/functions-nested/src/sort.rs
index b29c187f0679c..0d48ae4f9f8c4 100644
--- a/datafusion/functions-nested/src/sort.rs
+++ b/datafusion/functions-nested/src/sort.rs
@@ -132,7 +132,6 @@ fn get_array_sort_doc() -> &'static Documentation {
                 "Whether to sort nulls first(`NULLS FIRST` or `NULLS LAST`).",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-nested/src/string.rs b/datafusion/functions-nested/src/string.rs
index da4ab2bed49af..7ee3a2a99b774 100644
--- a/datafusion/functions-nested/src/string.rs
+++ b/datafusion/functions-nested/src/string.rs
@@ -205,7 +205,6 @@ fn get_array_to_string_doc() -> &'static Documentation {
                 "Optional. String to replace null values in the array. If not provided, nulls will be handled by default behavior.",
             )
             .build()
-            .unwrap()
     })
 }
 
@@ -318,7 +317,6 @@ fn get_string_to_array_doc() -> &'static Documentation {
                 "Substring values to be replaced with `NULL`.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-window/src/cume_dist.rs b/datafusion/functions-window/src/cume_dist.rs
index 500d96b56323d..ae89c1afeec82 100644
--- a/datafusion/functions-window/src/cume_dist.rs
+++ b/datafusion/functions-window/src/cume_dist.rs
@@ -101,7 +101,6 @@ fn get_cume_dist_doc() -> &'static Documentation {
             )
             .with_syntax_example("cume_dist()")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-window/src/lead_lag.rs b/datafusion/functions-window/src/lead_lag.rs
index bbe50cbbdc8af..daaaa3659d5d5 100644
--- a/datafusion/functions-window/src/lead_lag.rs
+++ b/datafusion/functions-window/src/lead_lag.rs
@@ -166,7 +166,6 @@ fn get_lag_doc() -> &'static Documentation {
             .with_argument("default", "The default value if the offset is \
             not within the partition. Must be of the same type as expression.")
             .build()
-            .unwrap()
     })
 }
 
@@ -188,7 +187,6 @@ fn get_lead_doc() -> &'static Documentation {
             .with_argument("default", "The default value if the offset is \
             not within the partition. Must be of the same type as expression.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-window/src/nth_value.rs b/datafusion/functions-window/src/nth_value.rs
index cff49c1f4c855..bfce60aae32f9 100644
--- a/datafusion/functions-window/src/nth_value.rs
+++ b/datafusion/functions-window/src/nth_value.rs
@@ -140,7 +140,6 @@ fn get_first_value_doc() -> &'static Documentation {
             .with_syntax_example("first_value(expression)")
             .with_argument("expression", "Expression to operate on")
             .build()
-            .unwrap()
     })
 }
 
@@ -157,7 +156,6 @@ fn get_last_value_doc() -> &'static Documentation {
             .with_syntax_example("last_value(expression)")
             .with_argument("expression", "Expression to operate on")
             .build()
-            .unwrap()
     })
 }
 
@@ -179,7 +177,6 @@ fn get_nth_value_doc() -> &'static Documentation {
             )
             .with_argument("n", "Integer. Specifies the n in nth")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-window/src/ntile.rs b/datafusion/functions-window/src/ntile.rs
index b0a7241f24cd4..5e35810fc6f0a 100644
--- a/datafusion/functions-window/src/ntile.rs
+++ b/datafusion/functions-window/src/ntile.rs
@@ -90,7 +90,6 @@ fn get_ntile_doc() -> &'static Documentation {
             .with_syntax_example("ntile(expression)")
             .with_argument("expression","An integer describing the number groups the partition should be split into")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-window/src/rank.rs b/datafusion/functions-window/src/rank.rs
index 06945e693eea4..a93400d65c56c 100644
--- a/datafusion/functions-window/src/rank.rs
+++ b/datafusion/functions-window/src/rank.rs
@@ -115,7 +115,6 @@ fn get_rank_doc() -> &'static Documentation {
             )
             .with_syntax_example("rank()")
             .build()
-            .unwrap()
     })
 }
 
@@ -132,7 +131,6 @@ fn get_dense_rank_doc() -> &'static Documentation {
             )
             .with_syntax_example("dense_rank()")
             .build()
-            .unwrap()
     })
 }
 
@@ -148,7 +146,6 @@ fn get_percent_rank_doc() -> &'static Documentation {
             )
             .with_syntax_example("percent_rank()")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions-window/src/row_number.rs b/datafusion/functions-window/src/row_number.rs
index 68f6fde232805..60c356321848f 100644
--- a/datafusion/functions-window/src/row_number.rs
+++ b/datafusion/functions-window/src/row_number.rs
@@ -73,7 +73,6 @@ fn get_row_number_doc() -> &'static Documentation {
             )
             .with_syntax_example("row_number()")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/Cargo.toml b/datafusion/functions/Cargo.toml
index 70a988dbfefb5..4d9ff34737b9d 100644
--- a/datafusion/functions/Cargo.toml
+++ b/datafusion/functions/Cargo.toml
@@ -72,8 +72,10 @@ blake2 = { version = "^0.10.2", optional = true }
 blake3 = { version = "1.0", optional = true }
 chrono = { workspace = true }
 datafusion-common = { workspace = true }
+datafusion-doc = { workspace = true }
 datafusion-execution = { workspace = true }
 datafusion-expr = { workspace = true }
+datafusion-macros = { workspace = true }
 hashbrown = { workspace = true, optional = true }
 hex = { version = "0.4", optional = true }
 itertools = { workspace = true }
diff --git a/datafusion/functions/src/core/arrow_cast.rs b/datafusion/functions/src/core/arrow_cast.rs
index a3e3feaa17e3d..3e727a1765388 100644
--- a/datafusion/functions/src/core/arrow_cast.rs
+++ b/datafusion/functions/src/core/arrow_cast.rs
@@ -164,7 +164,6 @@ fn get_arrow_cast_doc() -> &'static Documentation {
             .with_argument("expression", "Expression to cast. The expression can be a constant, column, or function, and any combination of operators.")
             .with_argument("datatype", "[Arrow data type](https://docs.rs/arrow/latest/arrow/datatypes/enum.DataType.html) name to cast to, as a string. The format is the same as that returned by [`arrow_typeof`]")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/core/arrowtypeof.rs b/datafusion/functions/src/core/arrowtypeof.rs
index a425aff6caad6..49df9a1a2858d 100644
--- a/datafusion/functions/src/core/arrowtypeof.rs
+++ b/datafusion/functions/src/core/arrowtypeof.rs
@@ -100,6 +100,5 @@ fn get_arrowtypeof_doc() -> &'static Documentation {
             )
             .with_argument("expression", "Expression to evaluate. The expression can be a constant, column, or function, and any combination of operators.")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/core/coalesce.rs b/datafusion/functions/src/core/coalesce.rs
index a05f3f08232c4..bde7b5a76b719 100644
--- a/datafusion/functions/src/core/coalesce.rs
+++ b/datafusion/functions/src/core/coalesce.rs
@@ -168,7 +168,6 @@ fn get_coalesce_doc() -> &'static Documentation {
                 "Expression to use if previous expressions are _null_. Can be a constant, column, or function, and any combination of arithmetic operators. Pass as many expression arguments as necessary."
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/core/getfield.rs b/datafusion/functions/src/core/getfield.rs
index c0af4d35966b1..94ab56ce1ed82 100644
--- a/datafusion/functions/src/core/getfield.rs
+++ b/datafusion/functions/src/core/getfield.rs
@@ -286,6 +286,5 @@ syntax such as `my_struct_col['field_name']` which results in a call to
                 "The field name in the map or struct to retrieve data for. Must evaluate to a string."
             )
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/core/greatest.rs b/datafusion/functions/src/core/greatest.rs
index 2553051155f3d..6fe09cba1fafb 100644
--- a/datafusion/functions/src/core/greatest.rs
+++ b/datafusion/functions/src/core/greatest.rs
@@ -22,9 +22,10 @@ use arrow::compute::SortOptions;
 use arrow::datatypes::DataType;
 use arrow_buffer::BooleanBuffer;
 use datafusion_common::{exec_err, plan_err, Result, ScalarValue};
+use datafusion_doc::Documentation;
 use datafusion_expr::binary::type_union_resolution;
 use datafusion_expr::scalar_doc_sections::DOC_SECTION_CONDITIONAL;
-use datafusion_expr::{ColumnarValue, Documentation};
+use datafusion_expr::ColumnarValue;
 use datafusion_expr::{ScalarUDFImpl, Signature, Volatility};
 use std::any::Any;
 use std::sync::{Arc, OnceLock};
@@ -248,7 +249,6 @@ fn get_greatest_doc() -> &'static Documentation {
                 "Expressions to compare and return the greatest value.. Can be a constant, column, or function, and any combination of arithmetic operators. Pass as many expression arguments as necessary."
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/core/named_struct.rs b/datafusion/functions/src/core/named_struct.rs
index 0211ed3fe691b..963b70514838e 100644
--- a/datafusion/functions/src/core/named_struct.rs
+++ b/datafusion/functions/src/core/named_struct.rs
@@ -201,6 +201,5 @@ a struct type of fields `field_a` and `field_b`:
             )
             .with_argument("expression_n_input", "Expression to include in the output struct. Can be a constant, column, or function, and any combination of arithmetic or string operators.")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/core/nullif.rs b/datafusion/functions/src/core/nullif.rs
index 05af8d3f589e3..4e7f8cb31e1c0 100644
--- a/datafusion/functions/src/core/nullif.rs
+++ b/datafusion/functions/src/core/nullif.rs
@@ -117,7 +117,6 @@ This can be used to perform the inverse operation of [`coalesce`](#coalesce).")
                 "Expression to compare to expression1. Can be a constant, column, or function, and any combination of operators."
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/core/nvl.rs b/datafusion/functions/src/core/nvl.rs
index 24b6f5fc14fef..d3b006fe6956b 100644
--- a/datafusion/functions/src/core/nvl.rs
+++ b/datafusion/functions/src/core/nvl.rs
@@ -133,7 +133,6 @@ fn get_nvl_doc() -> &'static Documentation {
                 "Expression to return if expr1 is null. Can be a constant, column, or function, and any combination of operators."
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/core/nvl2.rs b/datafusion/functions/src/core/nvl2.rs
index cfcdb4480787c..adb459fb857c0 100644
--- a/datafusion/functions/src/core/nvl2.rs
+++ b/datafusion/functions/src/core/nvl2.rs
@@ -133,7 +133,6 @@ fn get_nvl2_doc() -> &'static Documentation {
                 "Expression to return if expr1 is null. Can be a constant, column, or function, and any combination of operators."
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/core/struct.rs b/datafusion/functions/src/core/struct.rs
index 75d1d4eca6983..eeafbc2dadc3f 100644
--- a/datafusion/functions/src/core/struct.rs
+++ b/datafusion/functions/src/core/struct.rs
@@ -154,6 +154,5 @@ select struct(a as field_a, b) from t;
                 "expression1, expression_n",
                 "Expression to include in the output struct. Can be a constant, column, or function, any combination of arithmetic or string operators.")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/core/version.rs b/datafusion/functions/src/core/version.rs
index eac0aa38f0583..84bf838e9a9cc 100644
--- a/datafusion/functions/src/core/version.rs
+++ b/datafusion/functions/src/core/version.rs
@@ -109,7 +109,6 @@ fn get_version_doc() -> &'static Documentation {
 ```"#,
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/crypto/digest.rs b/datafusion/functions/src/crypto/digest.rs
index f738c6e3e40f2..e4d674db19c63 100644
--- a/datafusion/functions/src/crypto/digest.rs
+++ b/datafusion/functions/src/crypto/digest.rs
@@ -114,6 +114,5 @@ fn get_digest_doc() -> &'static Documentation {
 - blake3",
             )
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/crypto/md5.rs b/datafusion/functions/src/crypto/md5.rs
index 0e8ff1cd31928..7b1789335d216 100644
--- a/datafusion/functions/src/crypto/md5.rs
+++ b/datafusion/functions/src/crypto/md5.rs
@@ -114,6 +114,5 @@ fn get_md5_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", Some("String"))
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/crypto/sha224.rs b/datafusion/functions/src/crypto/sha224.rs
index f0bfcb9fab3ba..875260b0a171a 100644
--- a/datafusion/functions/src/crypto/sha224.rs
+++ b/datafusion/functions/src/crypto/sha224.rs
@@ -70,7 +70,6 @@ fn get_sha224_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", Some("String"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/crypto/sha256.rs b/datafusion/functions/src/crypto/sha256.rs
index 0a0044f72206f..d07c298311f84 100644
--- a/datafusion/functions/src/crypto/sha256.rs
+++ b/datafusion/functions/src/crypto/sha256.rs
@@ -94,6 +94,5 @@ fn get_sha256_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", Some("String"))
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/crypto/sha384.rs b/datafusion/functions/src/crypto/sha384.rs
index 7f8220e5f9d5f..d0a9236ec3a5a 100644
--- a/datafusion/functions/src/crypto/sha384.rs
+++ b/datafusion/functions/src/crypto/sha384.rs
@@ -94,6 +94,5 @@ fn get_sha384_doc() -> &'static Documentation {
             )
             .with_standard_argument("expression", Some("String"))
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/crypto/sha512.rs b/datafusion/functions/src/crypto/sha512.rs
index d2d51bfa53abf..cd19780c7b910 100644
--- a/datafusion/functions/src/crypto/sha512.rs
+++ b/datafusion/functions/src/crypto/sha512.rs
@@ -94,6 +94,5 @@ fn get_sha512_doc() -> &'static Documentation {
             )
             .with_argument("expression", "String")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/datetime/current_date.rs b/datafusion/functions/src/datetime/current_date.rs
index 3b819c470d1e1..d4c8be366d063 100644
--- a/datafusion/functions/src/datetime/current_date.rs
+++ b/datafusion/functions/src/datetime/current_date.rs
@@ -118,6 +118,5 @@ The `current_date()` return value is determined at query time and will return th
 "#)
             .with_syntax_example("current_date()")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/datetime/current_time.rs b/datafusion/functions/src/datetime/current_time.rs
index ca591f9223051..102262d0e1957 100644
--- a/datafusion/functions/src/datetime/current_time.rs
+++ b/datafusion/functions/src/datetime/current_time.rs
@@ -106,6 +106,5 @@ The `current_time()` return value is determined at query time and will return th
 "#)
             .with_syntax_example("current_time()")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/datetime/date_bin.rs b/datafusion/functions/src/datetime/date_bin.rs
index 671967a893251..cdb3beea48533 100644
--- a/datafusion/functions/src/datetime/date_bin.rs
+++ b/datafusion/functions/src/datetime/date_bin.rs
@@ -224,7 +224,6 @@ The following intervals are supported:
 - century
 ")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/datetime/date_part.rs b/datafusion/functions/src/datetime/date_part.rs
index 98c6b659a8240..eb221df9827e4 100644
--- a/datafusion/functions/src/datetime/date_part.rs
+++ b/datafusion/functions/src/datetime/date_part.rs
@@ -279,7 +279,6 @@ fn get_date_part_doc() -> &'static Documentation {
             )
             .with_alternative_syntax("extract(field FROM source)")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/datetime/date_trunc.rs b/datafusion/functions/src/datetime/date_trunc.rs
index 5ec308ef9c818..6fff805b720ec 100644
--- a/datafusion/functions/src/datetime/date_trunc.rs
+++ b/datafusion/functions/src/datetime/date_trunc.rs
@@ -274,7 +274,6 @@ fn get_date_trunc_doc() -> &'static Documentation {
                 "Time expression to operate on. Can be a constant, column, or function.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/datetime/from_unixtime.rs b/datafusion/functions/src/datetime/from_unixtime.rs
index 29b2f29b14c2f..5c6363b23741c 100644
--- a/datafusion/functions/src/datetime/from_unixtime.rs
+++ b/datafusion/functions/src/datetime/from_unixtime.rs
@@ -147,7 +147,6 @@ fn get_from_unixtime_doc() -> &'static Documentation {
 +-----------------------------------------------------------+
 ```"#)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/datetime/make_date.rs b/datafusion/functions/src/datetime/make_date.rs
index a13511f33398c..e8f604346741e 100644
--- a/datafusion/functions/src/datetime/make_date.rs
+++ b/datafusion/functions/src/datetime/make_date.rs
@@ -190,7 +190,6 @@ fn get_make_date_doc() -> &'static Documentation {
 Additional examples can be found [here](https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/make_date.rs)
 "#)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/datetime/now.rs b/datafusion/functions/src/datetime/now.rs
index cadc4fce04f1d..c2d42ec1bf784 100644
--- a/datafusion/functions/src/datetime/now.rs
+++ b/datafusion/functions/src/datetime/now.rs
@@ -115,6 +115,5 @@ The `now()` return value is determined at query time and will return the same ti
 "#)
             .with_syntax_example("now()")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/datetime/to_char.rs b/datafusion/functions/src/datetime/to_char.rs
index dd4ae7b8464ed..c2ae07cbaaa4c 100644
--- a/datafusion/functions/src/datetime/to_char.rs
+++ b/datafusion/functions/src/datetime/to_char.rs
@@ -172,7 +172,6 @@ fn get_to_char_doc() -> &'static Documentation {
 Additional examples can be found [here](https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/to_char.rs)
 "#)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/datetime/to_date.rs b/datafusion/functions/src/datetime/to_date.rs
index ff322ce319605..7d9a2b44fbb64 100644
--- a/datafusion/functions/src/datetime/to_date.rs
+++ b/datafusion/functions/src/datetime/to_date.rs
@@ -22,13 +22,46 @@ use arrow::error::ArrowError::ParseError;
 use arrow::{array::types::Date32Type, compute::kernels::cast_utils::Parser};
 use datafusion_common::error::DataFusionError;
 use datafusion_common::{arrow_err, exec_err, internal_datafusion_err, Result};
-use datafusion_expr::scalar_doc_sections::DOC_SECTION_DATETIME;
 use datafusion_expr::{
     ColumnarValue, Documentation, ScalarUDFImpl, Signature, Volatility,
 };
+use datafusion_macros::user_doc;
 use std::any::Any;
 use std::sync::OnceLock;
 
+#[user_doc(
+    doc_section(include = "true", label = "Time and Date Functions"),
+    description = r"Converts a value to a date (`YYYY-MM-DD`).
+Supports strings, integer and double types as input.
+Strings are parsed as YYYY-MM-DD (e.g. '2023-07-20') if no [Chrono format](https://docs.rs/chrono/latest/chrono/format/strftime/index.html)s are provided.
+Integers and doubles are interpreted as days since the unix epoch (`1970-01-01T00:00:00Z`).
+Returns the corresponding date.
+
+Note: `to_date` returns Date32, which represents its values as the number of days since unix epoch(`1970-01-01`) stored as signed 32 bit value. The largest supported date value is `9999-12-31`.",
+    syntax_example = "to_date('2017-05-31', '%Y-%m-%d')",
+    sql_example = "```sql\n\
+> select to_date('2023-01-31');\n\
++-----------------------------+\n\
+| to_date(Utf8(\"2023-01-31\")) |\n\
++-----------------------------+\n\
+| 2023-01-31                  |\n\
++-----------------------------+\n\
+> select to_date('2023/01/31', '%Y-%m-%d', '%Y/%m/%d');\n\
++---------------------------------------------------------------+\n\
+| to_date(Utf8(\"2023/01/31\"),Utf8(\"%Y-%m-%d\"),Utf8(\"%Y/%m/%d\")) |\n\
++---------------------------------------------------------------+\n\
+| 2023-01-31                                                    |\n\
++---------------------------------------------------------------+\n\
+```\n\n\
+Additional examples can be found [here](https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/to_date.rs)",
+    standard_argument(name = "expression", prefix = "String"),
+    argument(
+        name = "format_n",
+        description = r"Optional [Chrono format](https://docs.rs/chrono/latest/chrono/format/strftime/index.html) strings to use to parse the expression. Formats will be tried in the order
+  they appear with the first successful one being returned. If none of the formats successfully parse the expression
+  an error will be returned."
+    )
+)]
 #[derive(Debug)]
 pub struct ToDateFunc {
     signature: Signature,
@@ -79,50 +112,6 @@ impl ToDateFunc {
     }
 }
 
-static DOCUMENTATION: OnceLock<Documentation> = OnceLock::new();
-
-fn get_to_date_doc() -> &'static Documentation {
-    DOCUMENTATION.get_or_init(|| {
-        Documentation::builder()
-            .with_doc_section(DOC_SECTION_DATETIME)
-            .with_description(r#"Converts a value to a date (`YYYY-MM-DD`).
-Supports strings, integer and double types as input.
-Strings are parsed as YYYY-MM-DD (e.g. '2023-07-20') if no [Chrono format](https://docs.rs/chrono/latest/chrono/format/strftime/index.html)s are provided.
-Integers and doubles are interpreted as days since the unix epoch (`1970-01-01T00:00:00Z`).
-Returns the corresponding date.
-
-Note: `to_date` returns Date32, which represents its values as the number of days since unix epoch(`1970-01-01`) stored as signed 32 bit value. The largest supported date value is `9999-12-31`.
-"#)
-            .with_syntax_example("to_date('2017-05-31', '%Y-%m-%d')")
-            .with_sql_example(r#"```sql
-> select to_date('2023-01-31');
-+-----------------------------+
-| to_date(Utf8("2023-01-31")) |
-+-----------------------------+
-| 2023-01-31                  |
-+-----------------------------+
-> select to_date('2023/01/31', '%Y-%m-%d', '%Y/%m/%d');
-+---------------------------------------------------------------+
-| to_date(Utf8("2023/01/31"),Utf8("%Y-%m-%d"),Utf8("%Y/%m/%d")) |
-+---------------------------------------------------------------+
-| 2023-01-31                                                    |
-+---------------------------------------------------------------+
-```
-
-Additional examples can be found [here](https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/to_date.rs)
-"#)
-            .with_standard_argument("expression", Some("String"))
-            .with_argument(
-                "format_n",
-                "Optional [Chrono format](https://docs.rs/chrono/latest/chrono/format/strftime/index.html) strings to use to parse the expression. Formats will be tried in the order
-  they appear with the first successful one being returned. If none of the formats successfully parse the expression
-  an error will be returned.",
-            )
-            .build()
-            .unwrap()
-    })
-}
-
 impl ScalarUDFImpl for ToDateFunc {
     fn as_any(&self) -> &dyn Any {
         self
@@ -162,7 +151,7 @@ impl ScalarUDFImpl for ToDateFunc {
     }
 
     fn documentation(&self) -> Option<&Documentation> {
-        Some(get_to_date_doc())
+        self.doc()
     }
 }
 
@@ -466,7 +455,7 @@ mod tests {
 
         if let Ok(ColumnarValue::Scalar(ScalarValue::Date32(_))) = to_date_result {
             panic!(
-                "Conversion of {} succeded, but should have failed, ",
+                "Conversion of {} succeeded, but should have failed, ",
                 date_str
             );
         }
diff --git a/datafusion/functions/src/datetime/to_local_time.rs b/datafusion/functions/src/datetime/to_local_time.rs
index 5048b8fd47ec6..725a48dea4452 100644
--- a/datafusion/functions/src/datetime/to_local_time.rs
+++ b/datafusion/functions/src/datetime/to_local_time.rs
@@ -418,7 +418,6 @@ FROM (
 +---------------------------+
 ```"#)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/datetime/to_timestamp.rs b/datafusion/functions/src/datetime/to_timestamp.rs
index 78a7bf505dac1..4550a78e862a8 100644
--- a/datafusion/functions/src/datetime/to_timestamp.rs
+++ b/datafusion/functions/src/datetime/to_timestamp.rs
@@ -226,7 +226,6 @@ Note: `to_timestamp` returns `Timestamp(Nanosecond)`. The supported range for in
 Additional examples can be found [here](https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/to_timestamp.rs)
 "#)
             .build()
-            .unwrap()
     })
 }
 
@@ -314,7 +313,6 @@ fn get_to_timestamp_seconds_doc() -> &'static Documentation {
 Additional examples can be found [here](https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/to_timestamp.rs)
 "#)
             .build()
-            .unwrap()
     })
 }
 
@@ -404,7 +402,6 @@ fn get_to_timestamp_millis_doc() -> &'static Documentation {
 Additional examples can be found [here](https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/to_timestamp.rs)
 "#)
             .build()
-            .unwrap()
     })
 }
 
@@ -494,7 +491,6 @@ fn get_to_timestamp_micros_doc() -> &'static Documentation {
 Additional examples can be found [here](https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/to_timestamp.rs)
 "#)
             .build()
-            .unwrap()
     })
 }
 
@@ -584,7 +580,6 @@ fn get_to_timestamp_nanos_doc() -> &'static Documentation {
 Additional examples can be found [here](https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/to_timestamp.rs)
 "#)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/datetime/to_unixtime.rs b/datafusion/functions/src/datetime/to_unixtime.rs
index c291596c25200..74ee954a50ac9 100644
--- a/datafusion/functions/src/datetime/to_unixtime.rs
+++ b/datafusion/functions/src/datetime/to_unixtime.rs
@@ -128,6 +128,5 @@ fn get_to_unixtime_doc() -> &'static Documentation {
 ```
 "#)
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/encoding/inner.rs b/datafusion/functions/src/encoding/inner.rs
index 0649c7cbb5c0f..cd8691588fa27 100644
--- a/datafusion/functions/src/encoding/inner.rs
+++ b/datafusion/functions/src/encoding/inner.rs
@@ -70,7 +70,6 @@ fn get_encode_doc() -> &'static Documentation {
             .with_argument("format", "Supported formats are: `base64`, `hex`")
             .with_related_udf("decode")
             .build()
-            .unwrap()
     })
 }
 
@@ -157,7 +156,6 @@ fn get_decode_doc() -> &'static Documentation {
             .with_argument("format", "Same arguments as [encode](#encode)")
             .with_related_udf("encode")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/abs.rs b/datafusion/functions/src/math/abs.rs
index 798939162a63c..4ec2967d7584e 100644
--- a/datafusion/functions/src/math/abs.rs
+++ b/datafusion/functions/src/math/abs.rs
@@ -203,6 +203,5 @@ fn get_abs_doc() -> &'static Documentation {
             .with_syntax_example("abs(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/math/cot.rs b/datafusion/functions/src/math/cot.rs
index eded50a20d8d8..79e985b780c61 100644
--- a/datafusion/functions/src/math/cot.rs
+++ b/datafusion/functions/src/math/cot.rs
@@ -49,7 +49,6 @@ fn get_cot_doc() -> &'static Documentation {
             .with_syntax_example(r#"cot(numeric_expression)"#)
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/factorial.rs b/datafusion/functions/src/math/factorial.rs
index bacdf47524f4f..31ba135aa2f05 100644
--- a/datafusion/functions/src/math/factorial.rs
+++ b/datafusion/functions/src/math/factorial.rs
@@ -87,7 +87,6 @@ fn get_factorial_doc() -> &'static Documentation {
             .with_syntax_example("factorial(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/gcd.rs b/datafusion/functions/src/math/gcd.rs
index f4edef3acca38..cffc05e6df994 100644
--- a/datafusion/functions/src/math/gcd.rs
+++ b/datafusion/functions/src/math/gcd.rs
@@ -90,7 +90,6 @@ fn get_gcd_doc() -> &'static Documentation {
             .with_standard_argument("expression_x", Some("First numeric"))
             .with_standard_argument("expression_y", Some("Second numeric"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/iszero.rs b/datafusion/functions/src/math/iszero.rs
index 7e5d4fe77ffa0..e0d91c8abf98d 100644
--- a/datafusion/functions/src/math/iszero.rs
+++ b/datafusion/functions/src/math/iszero.rs
@@ -92,7 +92,6 @@ fn get_iszero_doc() -> &'static Documentation {
             .with_syntax_example("iszero(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/lcm.rs b/datafusion/functions/src/math/lcm.rs
index 64b07ce606f2f..55523b90a1bc7 100644
--- a/datafusion/functions/src/math/lcm.rs
+++ b/datafusion/functions/src/math/lcm.rs
@@ -91,7 +91,6 @@ fn get_lcm_doc() -> &'static Documentation {
             .with_standard_argument("expression_x", Some("First numeric"))
             .with_standard_argument("expression_y", Some("Second numeric"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/log.rs b/datafusion/functions/src/math/log.rs
index 14b6dc3e054ed..438fb34d15521 100644
--- a/datafusion/functions/src/math/log.rs
+++ b/datafusion/functions/src/math/log.rs
@@ -59,7 +59,6 @@ log(numeric_expression)"#)
             .with_standard_argument("base", Some("Base numeric"))
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/monotonicity.rs b/datafusion/functions/src/math/monotonicity.rs
index 19c85f4b6e3ce..6156cffd83828 100644
--- a/datafusion/functions/src/math/monotonicity.rs
+++ b/datafusion/functions/src/math/monotonicity.rs
@@ -48,7 +48,6 @@ pub fn get_acos_doc() -> &'static Documentation {
             .with_syntax_example("acos(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -81,7 +80,6 @@ pub fn get_acosh_doc() -> &'static Documentation {
             .with_syntax_example("acosh(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -110,7 +108,6 @@ pub fn get_asin_doc() -> &'static Documentation {
             .with_syntax_example("asin(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -131,7 +128,6 @@ pub fn get_asinh_doc() -> &'static Documentation {
             .with_syntax_example("asinh(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -150,7 +146,6 @@ pub fn get_atan_doc() -> &'static Documentation {
             .with_syntax_example("atan(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -181,7 +176,6 @@ pub fn get_atanh_doc() -> &'static Documentation {
             .with_syntax_example("atanh(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -206,7 +200,6 @@ pub fn get_atan2_doc() -> &'static Documentation {
             .with_argument("expression_x", r#"Second numeric expression to operate on.
   Can be a constant, column, or function, and any combination of arithmetic operators."#)
             .build()
-            .unwrap()
     })
 }
 
@@ -225,7 +218,6 @@ pub fn get_cbrt_doc() -> &'static Documentation {
             .with_syntax_example("cbrt(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -246,7 +238,6 @@ pub fn get_ceil_doc() -> &'static Documentation {
             .with_syntax_example("ceil(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -267,7 +258,6 @@ pub fn get_cos_doc() -> &'static Documentation {
             .with_syntax_example("cos(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -297,7 +287,6 @@ pub fn get_cosh_doc() -> &'static Documentation {
             .with_syntax_example("cosh(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -316,7 +305,6 @@ pub fn get_degrees_doc() -> &'static Documentation {
             .with_syntax_example("degrees(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -335,7 +323,6 @@ pub fn get_exp_doc() -> &'static Documentation {
             .with_syntax_example("exp(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -356,7 +343,6 @@ pub fn get_floor_doc() -> &'static Documentation {
             .with_syntax_example("floor(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -384,7 +370,6 @@ pub fn get_ln_doc() -> &'static Documentation {
             .with_syntax_example("ln(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -412,7 +397,6 @@ pub fn get_log2_doc() -> &'static Documentation {
             .with_syntax_example("log2(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -440,7 +424,6 @@ pub fn get_log10_doc() -> &'static Documentation {
             .with_syntax_example("log10(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -459,7 +442,6 @@ pub fn get_radians_doc() -> &'static Documentation {
             .with_syntax_example("radians(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -480,7 +462,6 @@ pub fn get_sin_doc() -> &'static Documentation {
             .with_syntax_example("sin(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -499,7 +480,6 @@ pub fn get_sinh_doc() -> &'static Documentation {
             .with_syntax_example("sinh(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -527,7 +507,6 @@ pub fn get_sqrt_doc() -> &'static Documentation {
             .with_syntax_example("sqrt(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -548,7 +527,6 @@ pub fn get_tan_doc() -> &'static Documentation {
             .with_syntax_example("tan(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
@@ -567,6 +545,5 @@ pub fn get_tanh_doc() -> &'static Documentation {
             .with_syntax_example("tanh(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/math/nans.rs b/datafusion/functions/src/math/nans.rs
index c1dd1aacc35a3..0fc476b192ab3 100644
--- a/datafusion/functions/src/math/nans.rs
+++ b/datafusion/functions/src/math/nans.rs
@@ -109,6 +109,5 @@ fn get_isnan_doc() -> &'static Documentation {
             .with_syntax_example("isnan(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/math/nanvl.rs b/datafusion/functions/src/math/nanvl.rs
index cfd21256dd961..aefa66283a5c9 100644
--- a/datafusion/functions/src/math/nanvl.rs
+++ b/datafusion/functions/src/math/nanvl.rs
@@ -96,7 +96,6 @@ Returns the second argument otherwise."#,
             .with_argument("expression_x", "Numeric expression to return if it's not _NaN_. Can be a constant, column, or function, and any combination of arithmetic operators.")
             .with_argument("expression_y", "Numeric expression to return if the first expression is _NaN_. Can be a constant, column, or function, and any combination of arithmetic operators.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/pi.rs b/datafusion/functions/src/math/pi.rs
index 70cc76f03c584..cbb0c3b2a828d 100644
--- a/datafusion/functions/src/math/pi.rs
+++ b/datafusion/functions/src/math/pi.rs
@@ -99,6 +99,5 @@ fn get_pi_doc() -> &'static Documentation {
             .with_description("Returns an approximate value of π.")
             .with_syntax_example("pi()")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/math/power.rs b/datafusion/functions/src/math/power.rs
index acf5f84df92b0..cd45d10e8e8ef 100644
--- a/datafusion/functions/src/math/power.rs
+++ b/datafusion/functions/src/math/power.rs
@@ -183,7 +183,6 @@ fn get_power_doc() -> &'static Documentation {
             .with_standard_argument("base", Some("Numeric"))
             .with_standard_argument("exponent", Some("Exponent numeric"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/random.rs b/datafusion/functions/src/math/random.rs
index 0026037c95bd6..0d9888fa4a028 100644
--- a/datafusion/functions/src/math/random.rs
+++ b/datafusion/functions/src/math/random.rs
@@ -98,6 +98,5 @@ The random seed is unique to each row."#,
             )
             .with_syntax_example("random()")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/math/round.rs b/datafusion/functions/src/math/round.rs
index 6000e5d765de1..1f35542e496f9 100644
--- a/datafusion/functions/src/math/round.rs
+++ b/datafusion/functions/src/math/round.rs
@@ -118,7 +118,6 @@ fn get_round_doc() -> &'static Documentation {
                 "Optional. The number of decimal places to round to. Defaults to 0.",
             )
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/signum.rs b/datafusion/functions/src/math/signum.rs
index 33ff630f309ff..b8afbb2865bb2 100644
--- a/datafusion/functions/src/math/signum.rs
+++ b/datafusion/functions/src/math/signum.rs
@@ -103,7 +103,6 @@ Zero and positive numbers return `1`."#,
             .with_syntax_example("signum(numeric_expression)")
             .with_standard_argument("numeric_expression", Some("Numeric"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/math/trunc.rs b/datafusion/functions/src/math/trunc.rs
index 9a05684d238e7..120d005d15f37 100644
--- a/datafusion/functions/src/math/trunc.rs
+++ b/datafusion/functions/src/math/trunc.rs
@@ -126,7 +126,6 @@ fn get_trunc_doc() -> &'static Documentation {
   right of the decimal point. If `decimal_places` is a negative
   integer, replaces digits to the left of the decimal point with `0`."#)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/regex/regexpcount.rs b/datafusion/functions/src/regex/regexpcount.rs
index 819463795b7fd..7e568d98cf665 100644
--- a/datafusion/functions/src/regex/regexpcount.rs
+++ b/datafusion/functions/src/regex/regexpcount.rs
@@ -138,7 +138,6 @@ fn get_regexp_count_doc() -> &'static Documentation {
   - **R**: enables CRLF mode: when multi-line mode is enabled, \r\n is used
   - **U**: swap the meaning of x* and x*?"#)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/regex/regexplike.rs b/datafusion/functions/src/regex/regexplike.rs
index 13de7888aa5fe..ec0fe243d4191 100644
--- a/datafusion/functions/src/regex/regexplike.rs
+++ b/datafusion/functions/src/regex/regexplike.rs
@@ -77,7 +77,6 @@ Additional examples can be found [here](https://github.com/apache/datafusion/blo
   - **R**: enables CRLF mode: when multi-line mode is enabled, \r\n is used
   - **U**: swap the meaning of x* and x*?"#)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/regex/regexpmatch.rs b/datafusion/functions/src/regex/regexpmatch.rs
index 019666bd7b2d4..ff4a210623471 100644
--- a/datafusion/functions/src/regex/regexpmatch.rs
+++ b/datafusion/functions/src/regex/regexpmatch.rs
@@ -148,7 +148,6 @@ Additional examples can be found [here](https://github.com/apache/datafusion/blo
   - **R**: enables CRLF mode: when multi-line mode is enabled, \r\n is used
   - **U**: swap the meaning of x* and x*?"#)
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/regex/regexpreplace.rs b/datafusion/functions/src/regex/regexpreplace.rs
index 4d8e5e5fe3e3b..ddec242d0b69b 100644
--- a/datafusion/functions/src/regex/regexpreplace.rs
+++ b/datafusion/functions/src/regex/regexpreplace.rs
@@ -167,7 +167,6 @@ Additional examples can be found [here](https://github.com/apache/datafusion/blo
 - **R**: enables CRLF mode: when multi-line mode is enabled, \r\n is used
 - **U**: swap the meaning of x* and x*?"#)
         .build()
-        .unwrap()
 })
 }
 
diff --git a/datafusion/functions/src/string/ascii.rs b/datafusion/functions/src/string/ascii.rs
index b76d70d7e9d26..4954c28610898 100644
--- a/datafusion/functions/src/string/ascii.rs
+++ b/datafusion/functions/src/string/ascii.rs
@@ -102,7 +102,6 @@ fn get_ascii_doc() -> &'static Documentation {
             .with_standard_argument("str", Some("String"))
             .with_related_udf("chr")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/bit_length.rs b/datafusion/functions/src/string/bit_length.rs
index cb815df15e4b3..a5b05f6c0fe67 100644
--- a/datafusion/functions/src/string/bit_length.rs
+++ b/datafusion/functions/src/string/bit_length.rs
@@ -114,6 +114,5 @@ fn get_bit_length_doc() -> &'static Documentation {
             .with_related_udf("length")
             .with_related_udf("octet_length")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/string/btrim.rs b/datafusion/functions/src/string/btrim.rs
index e215b18d9c3ce..932d1b2ad629b 100644
--- a/datafusion/functions/src/string/btrim.rs
+++ b/datafusion/functions/src/string/btrim.rs
@@ -129,7 +129,6 @@ fn get_btrim_doc() -> &'static Documentation {
             .with_related_udf("ltrim")
             .with_related_udf("rtrim")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/chr.rs b/datafusion/functions/src/string/chr.rs
index 0d94cab08d913..e17caeb09caea 100644
--- a/datafusion/functions/src/string/chr.rs
+++ b/datafusion/functions/src/string/chr.rs
@@ -128,6 +128,5 @@ fn get_chr_doc() -> &'static Documentation {
             .with_standard_argument("expression", Some("String"))
             .with_related_udf("ascii")
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/string/concat.rs b/datafusion/functions/src/string/concat.rs
index d49a2777b4ff8..d55d310bf3a08 100644
--- a/datafusion/functions/src/string/concat.rs
+++ b/datafusion/functions/src/string/concat.rs
@@ -285,7 +285,6 @@ fn get_concat_doc() -> &'static Documentation {
             .with_argument("str_n", "Subsequent string expressions to concatenate.")
             .with_related_udf("concat_ws")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/concat_ws.rs b/datafusion/functions/src/string/concat_ws.rs
index 98a75f121c35f..9118b335bda2b 100644
--- a/datafusion/functions/src/string/concat_ws.rs
+++ b/datafusion/functions/src/string/concat_ws.rs
@@ -299,7 +299,6 @@ fn get_concat_ws_doc() -> &'static Documentation {
             .with_argument("str_n", "Subsequent string expressions to concatenate.")
             .with_related_udf("concat")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/contains.rs b/datafusion/functions/src/string/contains.rs
index 3acd2464524da..de17668837346 100644
--- a/datafusion/functions/src/string/contains.rs
+++ b/datafusion/functions/src/string/contains.rs
@@ -98,7 +98,6 @@ fn get_contains_doc() -> &'static Documentation {
             .with_standard_argument("str", Some("String"))
             .with_argument("search_str", "The string to search for in str.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/ends_with.rs b/datafusion/functions/src/string/ends_with.rs
index 88978a35c0b7f..08e520d18f0b5 100644
--- a/datafusion/functions/src/string/ends_with.rs
+++ b/datafusion/functions/src/string/ends_with.rs
@@ -106,7 +106,6 @@ fn get_ends_with_doc() -> &'static Documentation {
             .with_standard_argument("str", Some("String"))
             .with_argument("substr", "Substring to test for.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/initcap.rs b/datafusion/functions/src/string/initcap.rs
index 5fd1e7929881a..96ea5087338f7 100644
--- a/datafusion/functions/src/string/initcap.rs
+++ b/datafusion/functions/src/string/initcap.rs
@@ -100,7 +100,6 @@ fn get_initcap_doc() -> &'static Documentation {
             .with_related_udf("lower")
             .with_related_udf("upper")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/levenshtein.rs b/datafusion/functions/src/string/levenshtein.rs
index 558e71239f84e..48e6dce8b479a 100644
--- a/datafusion/functions/src/string/levenshtein.rs
+++ b/datafusion/functions/src/string/levenshtein.rs
@@ -101,7 +101,6 @@ fn get_levenshtein_doc() -> &'static Documentation {
             .with_argument("str1", "String expression to compute Levenshtein distance with str2.")
             .with_argument("str2", "String expression to compute Levenshtein distance with str1.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/lower.rs b/datafusion/functions/src/string/lower.rs
index 78887fde0a8eb..de3bb2dc746d9 100644
--- a/datafusion/functions/src/string/lower.rs
+++ b/datafusion/functions/src/string/lower.rs
@@ -93,7 +93,6 @@ fn get_lower_doc() -> &'static Documentation {
             .with_related_udf("initcap")
             .with_related_udf("upper")
             .build()
-            .unwrap()
     })
 }
 #[cfg(test)]
diff --git a/datafusion/functions/src/string/ltrim.rs b/datafusion/functions/src/string/ltrim.rs
index 0b4c197646b6d..7e4d33cdc8321 100644
--- a/datafusion/functions/src/string/ltrim.rs
+++ b/datafusion/functions/src/string/ltrim.rs
@@ -128,7 +128,6 @@ fn get_ltrim_doc() -> &'static Documentation {
             .with_related_udf("btrim")
             .with_related_udf("rtrim")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/octet_length.rs b/datafusion/functions/src/string/octet_length.rs
index 89f71d4571998..523b2240e0d19 100644
--- a/datafusion/functions/src/string/octet_length.rs
+++ b/datafusion/functions/src/string/octet_length.rs
@@ -114,7 +114,6 @@ fn get_octet_length_doc() -> &'static Documentation {
             .with_related_udf("bit_length")
             .with_related_udf("length")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/overlay.rs b/datafusion/functions/src/string/overlay.rs
index 796776304f4ae..2fe6c0ca329eb 100644
--- a/datafusion/functions/src/string/overlay.rs
+++ b/datafusion/functions/src/string/overlay.rs
@@ -113,7 +113,6 @@ fn get_overlay_doc() -> &'static Documentation {
             .with_argument("pos", "The start position to start the replace in str.")
             .with_argument("count", "The count of characters to be replaced from start position of str. If not specified, will use substr length instead.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/repeat.rs b/datafusion/functions/src/string/repeat.rs
index 249ce15d6dbe3..5f0e06ece9ab4 100644
--- a/datafusion/functions/src/string/repeat.rs
+++ b/datafusion/functions/src/string/repeat.rs
@@ -104,7 +104,6 @@ fn get_repeat_doc() -> &'static Documentation {
             .with_standard_argument("str", Some("String"))
             .with_argument("n", "Number of times to repeat the input string.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/replace.rs b/datafusion/functions/src/string/replace.rs
index 91abc39da058a..fa40e3a17eaae 100644
--- a/datafusion/functions/src/string/replace.rs
+++ b/datafusion/functions/src/string/replace.rs
@@ -100,7 +100,6 @@ fn get_replace_doc() -> &'static Documentation {
             .with_standard_argument("substr", Some("Substring expression to replace in the input string. Substring"))
             .with_standard_argument("replacement", Some("Replacement substring"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/rtrim.rs b/datafusion/functions/src/string/rtrim.rs
index e934147efbbe3..a734bad34c316 100644
--- a/datafusion/functions/src/string/rtrim.rs
+++ b/datafusion/functions/src/string/rtrim.rs
@@ -128,7 +128,6 @@ fn get_rtrim_doc() -> &'static Documentation {
             .with_related_udf("btrim")
             .with_related_udf("ltrim")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/split_part.rs b/datafusion/functions/src/string/split_part.rs
index ea01cb1f56f9a..6e6dcdf319d43 100644
--- a/datafusion/functions/src/string/split_part.rs
+++ b/datafusion/functions/src/string/split_part.rs
@@ -202,7 +202,6 @@ fn get_split_part_doc() -> &'static Documentation {
             .with_argument("delimiter", "String or character to split on.")
             .with_argument("pos", "Position of the part to return.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/starts_with.rs b/datafusion/functions/src/string/starts_with.rs
index dce161a2e14bd..61e219ed00f96 100644
--- a/datafusion/functions/src/string/starts_with.rs
+++ b/datafusion/functions/src/string/starts_with.rs
@@ -105,7 +105,6 @@ fn get_starts_with_doc() -> &'static Documentation {
             .with_standard_argument("str", Some("String"))
             .with_argument("substr", "Substring to test for.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/to_hex.rs b/datafusion/functions/src/string/to_hex.rs
index e0033d2d1cb03..2de9314e6cfc5 100644
--- a/datafusion/functions/src/string/to_hex.rs
+++ b/datafusion/functions/src/string/to_hex.rs
@@ -136,7 +136,6 @@ fn get_to_hex_doc() -> &'static Documentation {
             )
             .with_standard_argument("int", Some("Integer"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/upper.rs b/datafusion/functions/src/string/upper.rs
index 5039d094f2d6d..dbc0ca4f6aae1 100644
--- a/datafusion/functions/src/string/upper.rs
+++ b/datafusion/functions/src/string/upper.rs
@@ -92,7 +92,6 @@ fn get_upper_doc() -> &'static Documentation {
             .with_related_udf("initcap")
             .with_related_udf("lower")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/string/uuid.rs b/datafusion/functions/src/string/uuid.rs
index 2282670dac799..eeb1620cdb970 100644
--- a/datafusion/functions/src/string/uuid.rs
+++ b/datafusion/functions/src/string/uuid.rs
@@ -101,6 +101,5 @@ fn get_uuid_doc() -> &'static Documentation {
 +--------------------------------------+
 ```"#)
             .build()
-            .unwrap()
     })
 }
diff --git a/datafusion/functions/src/unicode/character_length.rs b/datafusion/functions/src/unicode/character_length.rs
index eca8d3fd493d3..d8d016fff5997 100644
--- a/datafusion/functions/src/unicode/character_length.rs
+++ b/datafusion/functions/src/unicode/character_length.rs
@@ -107,7 +107,6 @@ fn get_character_length_doc() -> &'static Documentation {
             .with_related_udf("bit_length")
             .with_related_udf("octet_length")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/unicode/find_in_set.rs b/datafusion/functions/src/unicode/find_in_set.rs
index cad860e41088f..53d55b3c87284 100644
--- a/datafusion/functions/src/unicode/find_in_set.rs
+++ b/datafusion/functions/src/unicode/find_in_set.rs
@@ -104,7 +104,6 @@ fn get_find_in_set_doc() -> &'static Documentation {
             .with_argument("str", "String expression to find in strlist.")
             .with_argument("strlist", "A string list is a string composed of substrings separated by , characters.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/unicode/left.rs b/datafusion/functions/src/unicode/left.rs
index a6c2b9768f0bc..bb0c103b5f4c7 100644
--- a/datafusion/functions/src/unicode/left.rs
+++ b/datafusion/functions/src/unicode/left.rs
@@ -119,7 +119,6 @@ fn get_left_doc() -> &'static Documentation {
             .with_argument("n", "Number of characters to return.")
             .with_related_udf("right")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/unicode/lpad.rs b/datafusion/functions/src/unicode/lpad.rs
index a639bcedcd1ff..a1b51384947e4 100644
--- a/datafusion/functions/src/unicode/lpad.rs
+++ b/datafusion/functions/src/unicode/lpad.rs
@@ -124,7 +124,6 @@ fn get_lpad_doc() -> &'static Documentation {
             .with_argument("padding_str", "Optional string expression to pad with. Can be a constant, column, or function, and any combination of string operators. _Default is a space._")
             .with_related_udf("rpad")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/unicode/reverse.rs b/datafusion/functions/src/unicode/reverse.rs
index baf3b56636e2e..5078b4222611d 100644
--- a/datafusion/functions/src/unicode/reverse.rs
+++ b/datafusion/functions/src/unicode/reverse.rs
@@ -107,7 +107,6 @@ fn get_reverse_doc() -> &'static Documentation {
             )
             .with_standard_argument("str", Some("String"))
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/unicode/right.rs b/datafusion/functions/src/unicode/right.rs
index ab3b7ba1a27e6..10f361140379c 100644
--- a/datafusion/functions/src/unicode/right.rs
+++ b/datafusion/functions/src/unicode/right.rs
@@ -119,7 +119,6 @@ fn get_right_doc() -> &'static Documentation {
             .with_argument("n", "Number of characters to return")
             .with_related_udf("left")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/unicode/rpad.rs b/datafusion/functions/src/unicode/rpad.rs
index bd9d625105e9f..0336c933c1043 100644
--- a/datafusion/functions/src/unicode/rpad.rs
+++ b/datafusion/functions/src/unicode/rpad.rs
@@ -147,7 +147,6 @@ fn get_rpad_doc() -> &'static Documentation {
                            "String expression to pad with. Can be a constant, column, or function, and any combination of string operators. _Default is a space._")
             .with_related_udf("lpad")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/unicode/strpos.rs b/datafusion/functions/src/unicode/strpos.rs
index 9c84590f7f94e..dc596f3ca7d30 100644
--- a/datafusion/functions/src/unicode/strpos.rs
+++ b/datafusion/functions/src/unicode/strpos.rs
@@ -99,7 +99,6 @@ fn get_strpos_doc() -> &'static Documentation {
             .with_argument("substr", "Substring expression to search for.")
             .with_alternative_syntax("position(substr in origstr)")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/unicode/substr.rs b/datafusion/functions/src/unicode/substr.rs
index edfe57210b711..63af7626a6217 100644
--- a/datafusion/functions/src/unicode/substr.rs
+++ b/datafusion/functions/src/unicode/substr.rs
@@ -175,7 +175,6 @@ fn get_substr_doc() -> &'static Documentation {
             .with_argument("length", "Number of characters to extract. If not specified, returns the rest of the string after the start position.")
             .with_alternative_syntax("substring(str from start_pos for length)")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/unicode/substrindex.rs b/datafusion/functions/src/unicode/substrindex.rs
index c04839783f58f..d49156ee4a155 100644
--- a/datafusion/functions/src/unicode/substrindex.rs
+++ b/datafusion/functions/src/unicode/substrindex.rs
@@ -119,7 +119,6 @@ If count is negative, everything to the right of the final delimiter (counting f
             .with_argument("delim", "The string to find in str to split str.")
             .with_argument("count", "The number of times to search for the delimiter. Can be either a positive or negative number.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/functions/src/unicode/translate.rs b/datafusion/functions/src/unicode/translate.rs
index 845d34c708d4f..628b46d4b698f 100644
--- a/datafusion/functions/src/unicode/translate.rs
+++ b/datafusion/functions/src/unicode/translate.rs
@@ -105,7 +105,6 @@ fn get_translate_doc() -> &'static Documentation {
             .with_argument("chars", "Characters to translate.")
             .with_argument("translation", "Translation characters. Translation characters replace only characters at the same position in the **chars** string.")
             .build()
-            .unwrap()
     })
 }
 
diff --git a/datafusion/macros/Cargo.toml b/datafusion/macros/Cargo.toml
new file mode 100644
index 0000000000000..c5ac9d08dffa1
--- /dev/null
+++ b/datafusion/macros/Cargo.toml
@@ -0,0 +1,42 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[package]
+name = "datafusion-macros"
+description = "Procedural macros for DataFusion query engine"
+keywords = ["datafusion", "query", "sql"]
+version = { workspace = true }
+edition = { workspace = true }
+homepage = { workspace = true }
+repository = { workspace = true }
+license = { workspace = true }
+authors = { workspace = true }
+rust-version = { workspace = true }
+
+[lints]
+workspace = true
+
+[lib]
+name = "datafusion_macros"
+path = "src/lib.rs"
+proc-macro = true
+
+[dependencies]
+datafusion-doc = { workspace = true }
+proc-macro2 = "1.0"
+quote = "1.0.37"
+syn = { version = "2.0.79", features = ["full"] }
diff --git a/datafusion/macros/src/lib.rs b/datafusion/macros/src/lib.rs
new file mode 100644
index 0000000000000..319f1f209a0d1
--- /dev/null
+++ b/datafusion/macros/src/lib.rs
@@ -0,0 +1,216 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::{parse_macro_input, DeriveInput, LitStr};
+
+/// This procedural macro is intended to parse a rust custom attribute and create user documentation
+/// from it by constructing a `DocumentBuilder()` automatically. The `Documentation` can be
+/// retrieved from the `documentation()` method
+/// declared on `AggregateUDF`, `WindowUDFImpl`, `ScalarUDFImpl` traits.
+///
+/// Example:
+/// #[user_doc(
+///     doc_section(include = "true", label = "Time and Date Functions"),
+///     description = r"Converts a value to a date (`YYYY-MM-DD`)."
+///     sql_example = "```sql\n\
+/// \> select to_date('2023-01-31');\n\
+/// +-----------------------------+\n\
+/// | to_date(Utf8(\"2023-01-31\")) |\n\
+/// +-----------------------------+\n\
+/// | 2023-01-31                  |\n\
+/// +-----------------------------+\n\"),
+///     standard_argument(name = "expression", prefix = "String"),
+///     argument(
+///         name = "format_n",
+///         description = r"Optional [Chrono format](https://docs.rs/chrono/latest/chrono/format/strftime/index.html) strings to use to parse the expression. Formats will be tried in the order
+///   they appear with the first successful one being returned. If none of the formats successfully parse the expression
+///   an error will be returned."
+///    )
+/// )]
+/// #[derive(Debug)]
+/// pub struct ToDateFunc {
+///     signature: Signature,
+/// }
+///
+/// will generate the following code
+///
+/// #[derive(Debug)] pub struct ToDateFunc { signature : Signature, }
+/// use datafusion_doc :: DocSection;
+/// use datafusion_doc :: DocumentationBuilder;
+/// static DOCUMENTATION : OnceLock < Documentation > = OnceLock :: new();
+/// impl ToDateFunc
+/// {
+///     fn doc(& self) -> Option < & Documentation >
+///     {
+///         Some(DOCUMENTATION.get_or_init(||
+///         {
+///             Documentation ::
+///             builder().with_doc_section(DocSection
+///             {
+///                 include : true, label : "Time and Date Functions", description
+///                 : None
+///             }).with_description(r"Converts a value to a date (`YYYY-MM-DD`).")
+/// .with_syntax_example("to_date('2017-05-31', '%Y-%m-%d')".to_string()).with_sql_example("```sql\n\
+/// \> select to_date('2023-01-31');\n\
+/// +-----------------------------+\n\
+/// | to_date(Utf8(\"2023-01-31\")) |\n\
+/// +-----------------------------+\n\
+/// | 2023-01-31                  |\n\
+/// +-----------------------------+\n\)
+/// .with_standard_argument("expression", "String".into())
+/// .with_argument("format_n",
+///             r"Optional [Chrono format](https://docs.rs/chrono/latest/chrono/format/strftime/index.html) strings to use to parse the expression. Formats will be tried in the order
+///   they appear with the first successful one being returned. If none of the formats successfully parse the expression
+///   an error will be returned.").build()
+///         }))
+///     }
+/// }
+#[proc_macro_attribute]
+pub fn user_doc(args: TokenStream, input: TokenStream) -> TokenStream {
+    let mut doc_section_include: Option<LitStr> = None;
+    let mut doc_section_lbl: Option<LitStr> = None;
+    let mut doc_section_desc: Option<LitStr> = None;
+
+    let mut description: Option<LitStr> = None;
+    let mut syntax_example: Option<LitStr> = None;
+    let mut sql_example: Option<LitStr> = None;
+    let mut standard_args: Vec<(Option<LitStr>, Option<LitStr>)> = vec![];
+    let mut udf_args: Vec<(Option<LitStr>, Option<LitStr>)> = vec![];
+
+    let parser = syn::meta::parser(|meta| {
+        if meta.path.is_ident("doc_section") {
+            meta.parse_nested_meta(|meta| {
+                if meta.path.is_ident("include") {
+                    doc_section_include = meta.value()?.parse()?;
+                    return Ok(());
+                } else if meta.path.is_ident("label") {
+                    doc_section_lbl = meta.value()?.parse()?;
+                    return Ok(());
+                } else if meta.path.is_ident("description") {
+                    doc_section_desc = meta.value()?.parse()?;
+                    return Ok(());
+                }
+                Ok(())
+            })
+        } else if meta.path.is_ident("description") {
+            description = Some(meta.value()?.parse()?);
+            Ok(())
+        } else if meta.path.is_ident("syntax_example") {
+            syntax_example = Some(meta.value()?.parse()?);
+            Ok(())
+        } else if meta.path.is_ident("sql_example") {
+            sql_example = Some(meta.value()?.parse()?);
+            Ok(())
+        } else if meta.path.is_ident("standard_argument") {
+            let mut standard_arg: (Option<LitStr>, Option<LitStr>) = (None, None);
+            let m = meta.parse_nested_meta(|meta| {
+                if meta.path.is_ident("name") {
+                    standard_arg.0 = meta.value()?.parse()?;
+                    return Ok(());
+                } else if meta.path.is_ident("prefix") {
+                    standard_arg.1 = meta.value()?.parse()?;
+                    return Ok(());
+                }
+                Ok(())
+            });
+
+            standard_args.push(standard_arg.clone());
+
+            m
+        } else if meta.path.is_ident("argument") {
+            let mut arg: (Option<LitStr>, Option<LitStr>) = (None, None);
+            let m = meta.parse_nested_meta(|meta| {
+                if meta.path.is_ident("name") {
+                    arg.0 = meta.value()?.parse()?;
+                    return Ok(());
+                } else if meta.path.is_ident("description") {
+                    arg.1 = meta.value()?.parse()?;
+                    return Ok(());
+                }
+                Ok(())
+            });
+
+            udf_args.push(arg.clone());
+
+            m
+        } else {
+            Err(meta.error(format!("Unsupported property {:?}", meta.path.get_ident())))
+        }
+    });
+
+    parse_macro_input!(args with parser);
+
+    // Parse the input struct
+    let input = parse_macro_input!(input as DeriveInput);
+    let name = input.clone().ident;
+
+    let doc_section_include: bool = doc_section_include.unwrap().value().parse().unwrap();
+    let doc_section_description = doc_section_desc
+        .map(|desc| quote! { Some(#desc)})
+        .unwrap_or(quote! { None });
+
+    let udf_args = udf_args
+        .iter()
+        .map(|(name, desc)| {
+            quote! {
+                .with_argument(#name, #desc)
+            }
+        })
+        .collect::<Vec<_>>();
+
+    let standard_args = standard_args
+        .iter()
+        .map(|(name, desc)| {
+            quote! {
+                .with_standard_argument(#name, #desc.into())
+            }
+        })
+        .collect::<Vec<_>>();
+
+    let generated = quote! {
+        #input
+
+        use datafusion_doc::DocSection;
+        use datafusion_doc::DocumentationBuilder;
+
+        static DOCUMENTATION: OnceLock<Documentation> = OnceLock::new();
+
+        impl #name {
+                fn doc(&self) -> Option<&Documentation> {
+                    Some(DOCUMENTATION.get_or_init(|| {
+                        Documentation::builder()
+                        .with_doc_section(DocSection { include: #doc_section_include, label: #doc_section_lbl, description: #doc_section_description })
+                        .with_description(#description.to_string())
+                        .with_syntax_example(#syntax_example.to_string())
+                        .with_sql_example(#sql_example.to_string())
+                        #(#standard_args)*
+                        #(#udf_args)*
+                        .build()
+                    }))
+            }
+        }
+    };
+
+    // Debug the generated code if needed
+    // eprintln!("Generated code: {}", generated);
+
+    // Return the generated code
+    TokenStream::from(generated)
+}
