From 0676847ff01bbe7c53f706a9405ee6184fea00bc Mon Sep 17 00:00:00 2001 From: Shreyaskr1409 Date: Mon, 31 Mar 2025 19:17:54 +0530 Subject: [PATCH 1/6] Add formatting changes and fix the merge issue --- datafusion/physical-expr/src/aggregate.rs | 162 ++++++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/datafusion/physical-expr/src/aggregate.rs b/datafusion/physical-expr/src/aggregate.rs index ae3d9050fa628..5acf906124b6e 100644 --- a/datafusion/physical-expr/src/aggregate.rs +++ b/datafusion/physical-expr/src/aggregate.rs @@ -97,6 +97,168 @@ impl AggregateExprBuilder { /// Constructs an `AggregateFunctionExpr` from the builder /// /// Note that an [`Self::alias`] must be provided before calling this method. + /// + /// # Example: Create an `AggregateUDF` + /// + /// In the following example, `AggregateFunctionExpr` will be built using `AggregateExprBuilder` + /// which provides a build function. + /// + /// First we will create an `Accumulator` which will be used to further implement `AggregateUDFImpl`. + /// After implementing `AggregateUDFImpl`, it could be used to pass in as a parameter to create an `AggregateExprBuilder`. + /// `AggregateExprBuilder` could the be used to generate `AggregateFunctionExpr` after chaining + /// queries on top of each other. + /// + /// ``` + /// use std::any::Any; + /// use std::sync::OnceLock; + /// use std::sync::Arc; + /// use arrow::datatypes::DataType; + /// use datafusion_common::{DataFusionError, plan_err, Result, ScalarValue}; + /// use datafusion_expr::{col, ColumnarValue, Signature, Volatility, Expr, Documentation}; + /// use datafusion_expr::{AggregateUDFImpl, AggregateUDF, Accumulator, function::{AccumulatorArgs, StateFieldsArgs}}; + /// use datafusion_expr::window_doc_sections::DOC_SECTION_AGGREGATE; + /// use arrow::datatypes::Schema; + /// use arrow::datatypes::Field; + /// use arrow::array::Array; + /// + /// #[derive(Debug)] + /// struct FirstValueAccumulator { + /// value: Option, + /// data_type: DataType, + /// } + /// + /// impl Accumulator for FirstValueAccumulator { + /// fn update_batch(&mut self, values: &[Arc]) -> Result<()> { + /// if self.value.is_none() && !values.is_empty() { + /// let first_array = &values[0]; + /// for i in 0..first_array.len() { + /// if !first_array.is_null(i) { + /// self.value = Some(ScalarValue::try_from_array(first_array, i)?); + /// break; + /// } + /// } + /// } + /// Ok(()) + /// } + /// + /// fn merge_batch(&mut self, states: &[Arc]) -> Result<()> { + /// if self.value.is_none() && !states.is_empty() { + /// let first_array = &states[0]; + /// for i in 0..first_array.len() { + /// if !first_array.is_null(i) { + /// self.value = Some(ScalarValue::try_from_array(first_array, i)?); + /// break; + /// } + /// } + /// } + /// Ok(()) + /// } + /// + /// fn evaluate(&mut self) -> Result { + /// match &self.value { + /// Some(value) => Ok(value.clone()), + /// None => ScalarValue::try_from(&self.data_type), + /// } + /// } + /// + /// fn size(&self) -> usize { + /// std::mem::size_of_val(self) + /// } + /// + /// fn state(&mut self) -> Result> { + /// match &self.value { + /// Some(value) => Ok(vec![value.clone()]), + /// None => ScalarValue::try_from(&self.data_type).map(|v| vec![v]), + /// } + /// } + /// } + /// + /// #[derive(Debug, Clone)] + /// struct FirstValueUdf { + /// signature: Signature, + /// } + /// + /// impl FirstValueUdf { + /// fn new() -> Self { + /// Self { + /// signature: Signature::any(1, Volatility::Immutable), + /// } + /// } + /// } + /// + /// static DOCUMENTATION: OnceLock = OnceLock::new(); + /// + /// fn get_doc() -> &'static Documentation { + /// DOCUMENTATION.get_or_init(|| { + /// Documentation::builder( + /// DOC_SECTION_AGGREGATE, + /// "returns the first value in a set of values", + /// "first_value(column)" + /// ) + /// .with_argument("arg1", "The column to get the first value from") + /// .build() + /// }) + /// } + /// + /// impl AggregateUDFImpl for FirstValueUdf { + /// fn as_any(&self) -> &dyn Any { self } + /// fn name(&self) -> &str { "first_value" } + /// fn signature(&self) -> &Signature { &self.signature } + /// fn return_type(&self, args: &[DataType]) -> Result { + /// Ok(args[0].clone()) + /// } + /// + /// fn accumulator(&self, acc_args: AccumulatorArgs) -> Result> { + /// let input_type = acc_args.schema.field(0).data_type().clone(); + /// + /// Ok(Box::new(FirstValueAccumulator { + /// value: None, + /// data_type: input_type, + /// })) + /// } + /// + /// fn state_fields(&self, args: StateFieldsArgs) -> Result> { + /// Ok(vec![ + /// Field::new("value", args.return_type.clone(), true) + /// ]) + /// } + /// + /// fn documentation(&self) -> Option<&Documentation> { + /// Some(get_doc()) + /// } + /// } + /// + /// let first_value = AggregateUDF::from(FirstValueUdf::new()); + /// let expr = first_value.call(vec![col("a")]); + /// ``` + /// + /// # Example: Creating an ordered aggregate expression + /// + /// This example shows how to use `AggregateExprBuilder` to create a physical aggregate + /// expression with ordering: + /// + /// ```ignore + /// use std::sync::Arc; + /// use datafusion::physical_expr::expressions::Column; + /// use datafusion::physical_expr::aggregate::AggregateExprBuilder; + /// use datafusion::physical_plan::PhysicalExpr; + /// + /// let args = vec![Arc::new(Column::new("a", 0)) as Arc]; + /// let order_by = vec![Arc::new(Column::new("x", 1)) as Arc]; + /// + /// let aggregate_expr = AggregateExprBuilder::new( + /// Arc::new(first_value.clone()), // Use the UDF from previous example + /// args + /// ) + /// .order_by(order_by) + /// .alias("first_a_by_x") + /// .ignore_nulls() + /// .build() + /// .expect("Built aggregate expression successfully"); + /// ``` + /// + /// This creates a physical expression equivalent to SQL: + /// `first_value(a ORDER BY x) IGNORE NULLS AS first_a_by_x` pub fn build(self) -> Result { let Self { fun, From 21fb57a681c20b067a125590bd918b50a641ef0b Mon Sep 17 00:00:00 2001 From: Shreyaskr1409 Date: Mon, 31 Mar 2025 19:19:22 +0530 Subject: [PATCH 2/6] Fix formatting --- datafusion/physical-expr/src/aggregate.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datafusion/physical-expr/src/aggregate.rs b/datafusion/physical-expr/src/aggregate.rs index 5acf906124b6e..c4526bcabadec 100644 --- a/datafusion/physical-expr/src/aggregate.rs +++ b/datafusion/physical-expr/src/aggregate.rs @@ -97,9 +97,9 @@ impl AggregateExprBuilder { /// Constructs an `AggregateFunctionExpr` from the builder /// /// Note that an [`Self::alias`] must be provided before calling this method. - /// + /// /// # Example: Create an `AggregateUDF` - /// + /// /// In the following example, `AggregateFunctionExpr` will be built using `AggregateExprBuilder` /// which provides a build function. /// From e1f8656b4577d2413a7758a7439c276551f86c30 Mon Sep 17 00:00:00 2001 From: Shreyaskr1409 Date: Mon, 31 Mar 2025 19:26:40 +0530 Subject: [PATCH 3/6] Fixed a faulty statement --- datafusion/physical-expr/src/aggregate.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/datafusion/physical-expr/src/aggregate.rs b/datafusion/physical-expr/src/aggregate.rs index c4526bcabadec..ab8e581e5bd7d 100644 --- a/datafusion/physical-expr/src/aggregate.rs +++ b/datafusion/physical-expr/src/aggregate.rs @@ -254,7 +254,6 @@ impl AggregateExprBuilder { /// .alias("first_a_by_x") /// .ignore_nulls() /// .build() - /// .expect("Built aggregate expression successfully"); /// ``` /// /// This creates a physical expression equivalent to SQL: From c1bc801fcc55d0c2c526916a7dd51db4f5e8fa03 Mon Sep 17 00:00:00 2001 From: Shreyaskr1409 Date: Tue, 1 Apr 2025 22:16:03 +0530 Subject: [PATCH 4/6] Folded irrelevant sections from example --- datafusion/physical-expr/src/aggregate.rs | 298 +++++++++++----------- 1 file changed, 148 insertions(+), 150 deletions(-) diff --git a/datafusion/physical-expr/src/aggregate.rs b/datafusion/physical-expr/src/aggregate.rs index ab8e581e5bd7d..7d8e8b704b1b2 100644 --- a/datafusion/physical-expr/src/aggregate.rs +++ b/datafusion/physical-expr/src/aggregate.rs @@ -98,162 +98,160 @@ impl AggregateExprBuilder { /// /// Note that an [`Self::alias`] must be provided before calling this method. /// - /// # Example: Create an `AggregateUDF` + /// # Example: Create an [`AggregateUDF`] /// - /// In the following example, `AggregateFunctionExpr` will be built using `AggregateExprBuilder` - /// which provides a build function. - /// - /// First we will create an `Accumulator` which will be used to further implement `AggregateUDFImpl`. - /// After implementing `AggregateUDFImpl`, it could be used to pass in as a parameter to create an `AggregateExprBuilder`. - /// `AggregateExprBuilder` could the be used to generate `AggregateFunctionExpr` after chaining - /// queries on top of each other. + /// In the following example, [`AggregateFunctionExpr`] will be built using [`AggregateExprBuilder`] + /// which provides a build function. Full example could be accessed from the source file. /// /// ``` - /// use std::any::Any; - /// use std::sync::OnceLock; - /// use std::sync::Arc; - /// use arrow::datatypes::DataType; - /// use datafusion_common::{DataFusionError, plan_err, Result, ScalarValue}; - /// use datafusion_expr::{col, ColumnarValue, Signature, Volatility, Expr, Documentation}; - /// use datafusion_expr::{AggregateUDFImpl, AggregateUDF, Accumulator, function::{AccumulatorArgs, StateFieldsArgs}}; - /// use datafusion_expr::window_doc_sections::DOC_SECTION_AGGREGATE; - /// use arrow::datatypes::Schema; - /// use arrow::datatypes::Field; - /// use arrow::array::Array; - /// - /// #[derive(Debug)] - /// struct FirstValueAccumulator { - /// value: Option, - /// data_type: DataType, - /// } - /// - /// impl Accumulator for FirstValueAccumulator { - /// fn update_batch(&mut self, values: &[Arc]) -> Result<()> { - /// if self.value.is_none() && !values.is_empty() { - /// let first_array = &values[0]; - /// for i in 0..first_array.len() { - /// if !first_array.is_null(i) { - /// self.value = Some(ScalarValue::try_from_array(first_array, i)?); - /// break; - /// } - /// } - /// } - /// Ok(()) - /// } - /// - /// fn merge_batch(&mut self, states: &[Arc]) -> Result<()> { - /// if self.value.is_none() && !states.is_empty() { - /// let first_array = &states[0]; - /// for i in 0..first_array.len() { - /// if !first_array.is_null(i) { - /// self.value = Some(ScalarValue::try_from_array(first_array, i)?); - /// break; - /// } - /// } - /// } - /// Ok(()) - /// } - /// - /// fn evaluate(&mut self) -> Result { - /// match &self.value { - /// Some(value) => Ok(value.clone()), - /// None => ScalarValue::try_from(&self.data_type), - /// } - /// } - /// - /// fn size(&self) -> usize { - /// std::mem::size_of_val(self) - /// } - /// - /// fn state(&mut self) -> Result> { - /// match &self.value { - /// Some(value) => Ok(vec![value.clone()]), - /// None => ScalarValue::try_from(&self.data_type).map(|v| vec![v]), - /// } - /// } - /// } - /// - /// #[derive(Debug, Clone)] - /// struct FirstValueUdf { - /// signature: Signature, - /// } - /// - /// impl FirstValueUdf { - /// fn new() -> Self { - /// Self { - /// signature: Signature::any(1, Volatility::Immutable), - /// } - /// } - /// } - /// - /// static DOCUMENTATION: OnceLock = OnceLock::new(); - /// - /// fn get_doc() -> &'static Documentation { - /// DOCUMENTATION.get_or_init(|| { - /// Documentation::builder( - /// DOC_SECTION_AGGREGATE, - /// "returns the first value in a set of values", - /// "first_value(column)" - /// ) - /// .with_argument("arg1", "The column to get the first value from") - /// .build() - /// }) - /// } - /// - /// impl AggregateUDFImpl for FirstValueUdf { - /// fn as_any(&self) -> &dyn Any { self } - /// fn name(&self) -> &str { "first_value" } - /// fn signature(&self) -> &Signature { &self.signature } - /// fn return_type(&self, args: &[DataType]) -> Result { - /// Ok(args[0].clone()) - /// } - /// - /// fn accumulator(&self, acc_args: AccumulatorArgs) -> Result> { - /// let input_type = acc_args.schema.field(0).data_type().clone(); - /// - /// Ok(Box::new(FirstValueAccumulator { - /// value: None, - /// data_type: input_type, - /// })) - /// } + /// # use std::any::Any; + /// # use std::sync::OnceLock; + /// # use std::sync::Arc; + /// # use arrow::datatypes::DataType; + /// # use datafusion_common::{DataFusionError, plan_err, Result, ScalarValue}; + /// # use datafusion_expr::{col, ColumnarValue, Signature, Volatility, Expr, Documentation}; + /// # use datafusion_expr::{AggregateUDFImpl, AggregateUDF, Accumulator, function::{AccumulatorArgs, StateFieldsArgs}}; + /// # use datafusion_expr::window_doc_sections::DOC_SECTION_AGGREGATE; + /// # use arrow::datatypes::Schema; + /// # use arrow::datatypes::Field; + /// # use arrow::array::Array; + /// # + /// # #[derive(Debug)] + /// # struct FirstValueAccumulator { + /// # value: Option, + /// # data_type: DataType, + /// # } + /// # + /// # impl Accumulator for FirstValueAccumulator { + /// # fn update_batch(&mut self, values: &[Arc]) -> Result<()> { + /// # if self.value.is_none() && !values.is_empty() { + /// # let first_array = &values[0]; + /// # for i in 0..first_array.len() { + /// # if !first_array.is_null(i) { + /// # self.value = Some(ScalarValue::try_from_array(first_array, i)?); + /// # break; + /// # } + /// # } + /// # } + /// # Ok(()) + /// # } + /// # + /// # fn merge_batch(&mut self, states: &[Arc]) -> Result<()> { + /// # if self.value.is_none() && !states.is_empty() { + /// # let first_array = &states[0]; + /// # for i in 0..first_array.len() { + /// # if !first_array.is_null(i) { + /// # self.value = Some(ScalarValue::try_from_array(first_array, i)?); + /// # break; + /// # } + /// # } + /// # } + /// # Ok(()) + /// # } + /// # + /// # fn evaluate(&mut self) -> Result { + /// # match &self.value { + /// # Some(value) => Ok(value.clone()), + /// # None => ScalarValue::try_from(&self.data_type), + /// # } + /// # } + /// # + /// # fn size(&self) -> usize { + /// # std::mem::size_of_val(self) + /// # } + /// # + /// # fn state(&mut self) -> Result> { + /// # match &self.value { + /// # Some(value) => Ok(vec![value.clone()]), + /// # None => ScalarValue::try_from(&self.data_type).map(|v| vec![v]), + /// # } + /// # } + /// # } + /// # + /// # #[derive(Debug, Clone)] + /// # struct FirstValueUdf { + /// # signature: Signature, + /// # } + /// # + /// # impl FirstValueUdf { + /// # fn new() -> Self { + /// # Self { + /// # signature: Signature::any(1, Volatility::Immutable), + /// # } + /// # } + /// # } + /// # + /// # static DOCUMENTATION: OnceLock = OnceLock::new(); + /// # + /// # fn get_doc() -> &'static Documentation { + /// # DOCUMENTATION.get_or_init(|| { + /// # Documentation::builder( + /// # DOC_SECTION_AGGREGATE, + /// # "returns the first value in a set of values", + /// # "first_value(column)" + /// # ) + /// # .with_argument("arg1", "The column to get the first value from") + /// # .build() + /// # }) + /// # } + /// # + /// # impl AggregateUDFImpl for FirstValueUdf { + /// # fn as_any(&self) -> &dyn Any { self } + /// # fn name(&self) -> &str { "first_value" } + /// # fn signature(&self) -> &Signature { &self.signature } + /// # fn return_type(&self, args: &[DataType]) -> Result { + /// # Ok(args[0].clone()) + /// # } + /// # + /// # fn accumulator(&self, acc_args: AccumulatorArgs) -> Result> { + /// # let input_type = acc_args.schema.field(0).data_type().clone(); + /// # + /// # Ok(Box::new(FirstValueAccumulator { + /// # value: None, + /// # data_type: input_type, + /// # })) + /// # } + /// # + /// # fn state_fields(&self, args: StateFieldsArgs) -> Result> { + /// # Ok(vec![ + /// # Field::new("value", args.return_type.clone(), true) + /// # ]) + /// # } + /// # + /// # fn documentation(&self) -> Option<&Documentation> { + /// # Some(get_doc()) + /// # } + /// # } + /// # + /// # let first_value = AggregateUDF::from(FirstValueUdf::new()); + /// # let expr = first_value.call(vec![col("a")]); + /// # + /// # use datafusion_physical_expr::expressions::Column; + /// # use datafusion_physical_expr_common::physical_expr::PhysicalExpr; + /// # use datafusion_physical_expr::aggregate::AggregateExprBuilder; + /// # use datafusion_physical_expr::expressions::PhysicalSortExpr; + /// # use datafusion_physical_expr::PhysicalSortRequirement; + /// # + /// fn build_aggregate_expr() -> Result<()> { + /// let args = vec![Arc::new(Column::new("a", 0)) as Arc]; + /// let order_by = vec![PhysicalSortExpr { + /// expr: Arc::new(Column::new("x", 1)) as Arc, + /// options: Default::default(), + /// }]; + /// + /// let first_value = AggregateUDF::from(FirstValueUdf::new()); /// - /// fn state_fields(&self, args: StateFieldsArgs) -> Result> { - /// Ok(vec![ - /// Field::new("value", args.return_type.clone(), true) - /// ]) - /// } + /// let aggregate_expr = AggregateExprBuilder::new( + /// Arc::new(first_value), + /// args + /// ) + /// .order_by(order_by.into()) + /// .alias("first_a_by_x") + /// .ignore_nulls() + /// .build()?; /// - /// fn documentation(&self) -> Option<&Documentation> { - /// Some(get_doc()) - /// } + /// Ok(()) /// } - /// - /// let first_value = AggregateUDF::from(FirstValueUdf::new()); - /// let expr = first_value.call(vec![col("a")]); - /// ``` - /// - /// # Example: Creating an ordered aggregate expression - /// - /// This example shows how to use `AggregateExprBuilder` to create a physical aggregate - /// expression with ordering: - /// - /// ```ignore - /// use std::sync::Arc; - /// use datafusion::physical_expr::expressions::Column; - /// use datafusion::physical_expr::aggregate::AggregateExprBuilder; - /// use datafusion::physical_plan::PhysicalExpr; - /// - /// let args = vec![Arc::new(Column::new("a", 0)) as Arc]; - /// let order_by = vec![Arc::new(Column::new("x", 1)) as Arc]; - /// - /// let aggregate_expr = AggregateExprBuilder::new( - /// Arc::new(first_value.clone()), // Use the UDF from previous example - /// args - /// ) - /// .order_by(order_by) - /// .alias("first_a_by_x") - /// .ignore_nulls() - /// .build() /// ``` /// /// This creates a physical expression equivalent to SQL: From 60516f2cf571ec6d73557e9de1e4cccce3253c29 Mon Sep 17 00:00:00 2001 From: Shreyaskr1409 Date: Tue, 1 Apr 2025 22:24:55 +0530 Subject: [PATCH 5/6] Fix formatting --- datafusion/physical-expr/src/aggregate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafusion/physical-expr/src/aggregate.rs b/datafusion/physical-expr/src/aggregate.rs index 7d8e8b704b1b2..fdb781de734e0 100644 --- a/datafusion/physical-expr/src/aggregate.rs +++ b/datafusion/physical-expr/src/aggregate.rs @@ -238,7 +238,7 @@ impl AggregateExprBuilder { /// expr: Arc::new(Column::new("x", 1)) as Arc, /// options: Default::default(), /// }]; - /// + /// /// let first_value = AggregateUDF::from(FirstValueUdf::new()); /// /// let aggregate_expr = AggregateExprBuilder::new( From 0cbf59a194c1e186c595f383ef57dd1bffbec0ab Mon Sep 17 00:00:00 2001 From: Shreyaskr1409 Date: Wed, 2 Apr 2025 10:01:45 +0530 Subject: [PATCH 6/6] Add unimplemented!() --- datafusion/physical-expr/src/aggregate.rs | 101 ++++------------------ 1 file changed, 15 insertions(+), 86 deletions(-) diff --git a/datafusion/physical-expr/src/aggregate.rs b/datafusion/physical-expr/src/aggregate.rs index fdb781de734e0..49912954ac81c 100644 --- a/datafusion/physical-expr/src/aggregate.rs +++ b/datafusion/physical-expr/src/aggregate.rs @@ -105,68 +105,12 @@ impl AggregateExprBuilder { /// /// ``` /// # use std::any::Any; - /// # use std::sync::OnceLock; /// # use std::sync::Arc; /// # use arrow::datatypes::DataType; - /// # use datafusion_common::{DataFusionError, plan_err, Result, ScalarValue}; - /// # use datafusion_expr::{col, ColumnarValue, Signature, Volatility, Expr, Documentation}; + /// # use datafusion_common::{Result, ScalarValue}; + /// # use datafusion_expr::{col, ColumnarValue, Documentation, Signature, Volatility, Expr}; /// # use datafusion_expr::{AggregateUDFImpl, AggregateUDF, Accumulator, function::{AccumulatorArgs, StateFieldsArgs}}; - /// # use datafusion_expr::window_doc_sections::DOC_SECTION_AGGREGATE; - /// # use arrow::datatypes::Schema; /// # use arrow::datatypes::Field; - /// # use arrow::array::Array; - /// # - /// # #[derive(Debug)] - /// # struct FirstValueAccumulator { - /// # value: Option, - /// # data_type: DataType, - /// # } - /// # - /// # impl Accumulator for FirstValueAccumulator { - /// # fn update_batch(&mut self, values: &[Arc]) -> Result<()> { - /// # if self.value.is_none() && !values.is_empty() { - /// # let first_array = &values[0]; - /// # for i in 0..first_array.len() { - /// # if !first_array.is_null(i) { - /// # self.value = Some(ScalarValue::try_from_array(first_array, i)?); - /// # break; - /// # } - /// # } - /// # } - /// # Ok(()) - /// # } - /// # - /// # fn merge_batch(&mut self, states: &[Arc]) -> Result<()> { - /// # if self.value.is_none() && !states.is_empty() { - /// # let first_array = &states[0]; - /// # for i in 0..first_array.len() { - /// # if !first_array.is_null(i) { - /// # self.value = Some(ScalarValue::try_from_array(first_array, i)?); - /// # break; - /// # } - /// # } - /// # } - /// # Ok(()) - /// # } - /// # - /// # fn evaluate(&mut self) -> Result { - /// # match &self.value { - /// # Some(value) => Ok(value.clone()), - /// # None => ScalarValue::try_from(&self.data_type), - /// # } - /// # } - /// # - /// # fn size(&self) -> usize { - /// # std::mem::size_of_val(self) - /// # } - /// # - /// # fn state(&mut self) -> Result> { - /// # match &self.value { - /// # Some(value) => Ok(vec![value.clone()]), - /// # None => ScalarValue::try_from(&self.data_type).map(|v| vec![v]), - /// # } - /// # } - /// # } /// # /// # #[derive(Debug, Clone)] /// # struct FirstValueUdf { @@ -181,45 +125,30 @@ impl AggregateExprBuilder { /// # } /// # } /// # - /// # static DOCUMENTATION: OnceLock = OnceLock::new(); - /// # - /// # fn get_doc() -> &'static Documentation { - /// # DOCUMENTATION.get_or_init(|| { - /// # Documentation::builder( - /// # DOC_SECTION_AGGREGATE, - /// # "returns the first value in a set of values", - /// # "first_value(column)" - /// # ) - /// # .with_argument("arg1", "The column to get the first value from") - /// # .build() - /// # }) - /// # } - /// # /// # impl AggregateUDFImpl for FirstValueUdf { - /// # fn as_any(&self) -> &dyn Any { self } - /// # fn name(&self) -> &str { "first_value" } - /// # fn signature(&self) -> &Signature { &self.signature } + /// # fn as_any(&self) -> &dyn Any { + /// # unimplemented!() + /// # } + /// # fn name(&self) -> &str { + /// # unimplemented!() + /// } + /// # fn signature(&self) -> &Signature { + /// # unimplemented!() + /// # } /// # fn return_type(&self, args: &[DataType]) -> Result { - /// # Ok(args[0].clone()) + /// # unimplemented!() /// # } /// # /// # fn accumulator(&self, acc_args: AccumulatorArgs) -> Result> { - /// # let input_type = acc_args.schema.field(0).data_type().clone(); - /// # - /// # Ok(Box::new(FirstValueAccumulator { - /// # value: None, - /// # data_type: input_type, - /// # })) + /// # unimplemented!() /// # } /// # /// # fn state_fields(&self, args: StateFieldsArgs) -> Result> { - /// # Ok(vec![ - /// # Field::new("value", args.return_type.clone(), true) - /// # ]) + /// # unimplemented!() /// # } /// # /// # fn documentation(&self) -> Option<&Documentation> { - /// # Some(get_doc()) + /// # unimplemented!() /// # } /// # } /// #