| // 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. |
| |
| //! Convenience macros for defining a user-defined window function |
| //! and associated expression API (fluent style). |
| //! |
| //! See [`define_udwf_and_expr!`] for usage examples. |
| //! |
| //! [`define_udwf_and_expr!`]: crate::define_udwf_and_expr! |
| |
| /// Lazily initializes a user-defined window function exactly once |
| /// when called concurrently. Repeated calls return a reference to the |
| /// same instance. |
| /// |
| /// # Parameters |
| /// |
| /// * `$UDWF`: The struct which defines the [`Signature`](datafusion_expr::Signature) |
| /// of the user-defined window function. |
| /// * `$OUT_FN_NAME`: The basename to generate a unique function name like |
| /// `$OUT_FN_NAME_udwf`. |
| /// * `$DOC`: Doc comments for UDWF. |
| /// * (optional) `$CTOR`: Pass a custom constructor. When omitted it |
| /// automatically resolves to `$UDWF::default()`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use std::any::Any; |
| /// use arrow::datatypes::FieldRef; |
| /// # use datafusion_common::arrow::datatypes::{DataType, Field}; |
| /// # use datafusion_expr::{PartitionEvaluator, Signature, Volatility, WindowUDFImpl}; |
| /// # |
| /// # use datafusion_functions_window_common::field::WindowUDFFieldArgs; |
| /// # use datafusion_functions_window::get_or_init_udwf; |
| /// # use datafusion_functions_window_common::partition::PartitionEvaluatorArgs; |
| /// # |
| /// /// Defines the `simple_udwf()` user-defined window function. |
| /// get_or_init_udwf!( |
| /// SimpleUDWF, |
| /// simple, |
| /// "Simple user-defined window function doc comment." |
| /// ); |
| /// # |
| /// # assert_eq!(simple_udwf().name(), "simple_user_defined_window_function"); |
| /// # |
| /// # #[derive(Debug, PartialEq, Eq, Hash)] |
| /// # struct SimpleUDWF { |
| /// # signature: Signature, |
| /// # } |
| /// # |
| /// # impl Default for SimpleUDWF { |
| /// # fn default() -> Self { |
| /// # Self { |
| /// # signature: Signature::any(0, Volatility::Immutable), |
| /// # } |
| /// # } |
| /// # } |
| /// # |
| /// # impl WindowUDFImpl for SimpleUDWF { |
| /// # fn as_any(&self) -> &dyn Any { |
| /// # self |
| /// # } |
| /// # fn name(&self) -> &str { |
| /// # "simple_user_defined_window_function" |
| /// # } |
| /// # fn signature(&self) -> &Signature { |
| /// # &self.signature |
| /// # } |
| /// # fn partition_evaluator( |
| /// # &self, |
| /// # _partition_evaluator_args: PartitionEvaluatorArgs, |
| /// # ) -> datafusion_common::Result<Box<dyn PartitionEvaluator>> { |
| /// # unimplemented!() |
| /// # } |
| /// # fn field(&self, field_args: WindowUDFFieldArgs) -> datafusion_common::Result<FieldRef> { |
| /// # Ok(Field::new(field_args.name(), DataType::Int64, false).into()) |
| /// # } |
| /// # } |
| /// # |
| /// ``` |
| #[macro_export] |
| macro_rules! get_or_init_udwf { |
| ($UDWF:ident, $OUT_FN_NAME:ident, $DOC:expr) => { |
| get_or_init_udwf!($UDWF, $OUT_FN_NAME, $DOC, $UDWF::default); |
| }; |
| |
| ($UDWF:ident, $OUT_FN_NAME:ident, $DOC:expr, $CTOR:path) => { |
| paste::paste! { |
| #[doc = concat!(" Returns a [`WindowUDF`](datafusion_expr::WindowUDF) for [`", stringify!($OUT_FN_NAME), "`].")] |
| #[doc = ""] |
| #[doc = concat!(" ", $DOC)] |
| pub fn [<$OUT_FN_NAME _udwf>]() -> std::sync::Arc<datafusion_expr::WindowUDF> { |
| // Singleton instance of UDWF, ensures it is only created once. |
| static INSTANCE: std::sync::LazyLock<std::sync::Arc<datafusion_expr::WindowUDF>> = |
| std::sync::LazyLock::new(|| { |
| std::sync::Arc::new(datafusion_expr::WindowUDF::from($CTOR())) |
| }); |
| std::sync::Arc::clone(&INSTANCE) |
| } |
| } |
| }; |
| } |
| |
| /// Create a [`WindowFunction`] expression that exposes a fluent API |
| /// which you can use to build more complex expressions. |
| /// |
| /// [`WindowFunction`]: datafusion_expr::Expr::WindowFunction |
| /// |
| /// # Parameters |
| /// |
| /// * `$UDWF`: The struct which defines the [`Signature`] of the |
| /// user-defined window function. |
| /// * `$OUT_FN_NAME`: The basename to generate a unique function name like |
| /// `$OUT_FN_NAME_udwf`. |
| /// * `$DOC`: Doc comments for UDWF. |
| /// * (optional) `[$($PARAM:ident),+]`: An array of 1 or more parameters |
| /// for the generated function. The type of parameters is [`Expr`]. |
| /// When omitted this creates a function with zero parameters. |
| /// |
| /// [`Signature`]: datafusion_expr::Signature |
| /// [`Expr`]: datafusion_expr::Expr |
| /// |
| /// # Example |
| /// |
| /// 1. With Zero Parameters |
| /// ``` |
| /// # use std::any::Any; |
| /// use arrow::datatypes::FieldRef; |
| /// # use datafusion_common::arrow::datatypes::{DataType, Field}; |
| /// # use datafusion_expr::{PartitionEvaluator, Signature, Volatility, WindowUDFImpl}; |
| /// # use datafusion_functions_window::{create_udwf_expr, get_or_init_udwf}; |
| /// # use datafusion_functions_window_common::field::WindowUDFFieldArgs; |
| /// # use datafusion_functions_window_common::partition::PartitionEvaluatorArgs; |
| /// |
| /// # get_or_init_udwf!( |
| /// # RowNumber, |
| /// # row_number, |
| /// # "Returns a unique row number for each row in window partition beginning at 1." |
| /// # ); |
| /// /// Creates `row_number()` API which has zero parameters: |
| /// /// |
| /// /// ``` |
| /// /// /// Returns a unique row number for each row in window partition |
| /// /// /// beginning at 1. |
| /// /// pub fn row_number() -> datafusion_expr::Expr { |
| /// /// row_number_udwf().call(vec![]) |
| /// /// } |
| /// /// ``` |
| /// create_udwf_expr!( |
| /// RowNumber, |
| /// row_number, |
| /// "Returns a unique row number for each row in window partition beginning at 1." |
| /// ); |
| /// # |
| /// # assert_eq!( |
| /// # row_number().name_for_alias().unwrap(), |
| /// # "row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" |
| /// # ); |
| /// # |
| /// # #[derive(Debug, PartialEq, Eq, Hash)] |
| /// # struct RowNumber { |
| /// # signature: Signature, |
| /// # } |
| /// # impl Default for RowNumber { |
| /// # fn default() -> Self { |
| /// # Self { |
| /// # signature: Signature::any(0, Volatility::Immutable), |
| /// # } |
| /// # } |
| /// # } |
| /// # impl WindowUDFImpl for RowNumber { |
| /// # fn as_any(&self) -> &dyn Any { |
| /// # self |
| /// # } |
| /// # fn name(&self) -> &str { |
| /// # "row_number" |
| /// # } |
| /// # fn signature(&self) -> &Signature { |
| /// # &self.signature |
| /// # } |
| /// # fn partition_evaluator( |
| /// # &self, |
| /// # _partition_evaluator_args: PartitionEvaluatorArgs, |
| /// # ) -> datafusion_common::Result<Box<dyn PartitionEvaluator>> { |
| /// # unimplemented!() |
| /// # } |
| /// # fn field(&self, field_args: WindowUDFFieldArgs) -> datafusion_common::Result<FieldRef> { |
| /// # Ok(Field::new(field_args.name(), DataType::UInt64, false).into()) |
| /// # } |
| /// # } |
| /// ``` |
| /// |
| /// 2. With Multiple Parameters |
| /// ``` |
| /// # use std::any::Any; |
| /// use arrow::datatypes::FieldRef; |
| /// # |
| /// # use datafusion_expr::{ |
| /// # PartitionEvaluator, Signature, TypeSignature, Volatility, WindowUDFImpl, |
| /// # }; |
| /// # |
| /// # use datafusion_functions_window::{create_udwf_expr, get_or_init_udwf}; |
| /// # use datafusion_functions_window_common::field::WindowUDFFieldArgs; |
| /// # |
| /// # use datafusion_common::arrow::datatypes::Field; |
| /// # use datafusion_common::ScalarValue; |
| /// # use datafusion_expr::{col, lit}; |
| /// # use datafusion_functions_window_common::partition::PartitionEvaluatorArgs; |
| /// # |
| /// # get_or_init_udwf!(Lead, lead, "user-defined window function"); |
| /// # |
| /// /// Creates `lead(expr, offset, default)` with 3 parameters: |
| /// /// |
| /// /// ``` |
| /// /// /// Returns a value evaluated at the row that is offset rows |
| /// /// /// after the current row within the partition. |
| /// /// pub fn lead( |
| /// /// expr: datafusion_expr::Expr, |
| /// /// offset: datafusion_expr::Expr, |
| /// /// default: datafusion_expr::Expr, |
| /// /// ) -> datafusion_expr::Expr { |
| /// /// lead_udwf().call(vec![expr, offset, default]) |
| /// /// } |
| /// /// ``` |
| /// create_udwf_expr!( |
| /// Lead, |
| /// lead, |
| /// [expr, offset, default], |
| /// "Returns a value evaluated at the row that is offset rows after the current row within the partition." |
| /// ); |
| /// # |
| /// # assert_eq!( |
| /// # lead(col("a"), lit(1i64), lit(ScalarValue::Null)) |
| /// # .name_for_alias() |
| /// # .unwrap(), |
| /// # "lead(a,Int64(1),NULL) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" |
| /// # ); |
| /// # |
| /// # #[derive(Debug, PartialEq, Eq, Hash)] |
| /// # struct Lead { |
| /// # signature: Signature, |
| /// # } |
| /// # |
| /// # impl Default for Lead { |
| /// # fn default() -> Self { |
| /// # Self { |
| /// # signature: Signature::one_of( |
| /// # vec![ |
| /// # TypeSignature::Any(1), |
| /// # TypeSignature::Any(2), |
| /// # TypeSignature::Any(3), |
| /// # ], |
| /// # Volatility::Immutable, |
| /// # ), |
| /// # } |
| /// # } |
| /// # } |
| /// # |
| /// # impl WindowUDFImpl for Lead { |
| /// # fn as_any(&self) -> &dyn Any { |
| /// # self |
| /// # } |
| /// # fn name(&self) -> &str { |
| /// # "lead" |
| /// # } |
| /// # fn signature(&self) -> &Signature { |
| /// # &self.signature |
| /// # } |
| /// # fn partition_evaluator( |
| /// # &self, |
| /// # partition_evaluator_args: PartitionEvaluatorArgs, |
| /// # ) -> datafusion_common::Result<Box<dyn PartitionEvaluator>> { |
| /// # unimplemented!() |
| /// # } |
| /// # fn field(&self, field_args: WindowUDFFieldArgs) -> datafusion_common::Result<FieldRef> { |
| /// # Ok(Field::new( |
| /// # field_args.name(), |
| /// # field_args.get_input_field(0).unwrap().data_type().clone(), |
| /// # false, |
| /// # ).into()) |
| /// # } |
| /// # } |
| /// ``` |
| #[macro_export] |
| macro_rules! create_udwf_expr { |
| // zero arguments |
| ($UDWF:ident, $OUT_FN_NAME:ident, $DOC:expr) => { |
| paste::paste! { |
| #[doc = " Create a [`WindowFunction`](datafusion_expr::Expr::WindowFunction) expression for"] |
| #[doc = concat!(" `", stringify!($UDWF), "` user-defined window function.")] |
| #[doc = ""] |
| #[doc = concat!(" ", $DOC)] |
| pub fn $OUT_FN_NAME() -> datafusion_expr::Expr { |
| [<$OUT_FN_NAME _udwf>]().call(vec![]) |
| } |
| } |
| }; |
| |
| // 1 or more arguments |
| ($UDWF:ident, $OUT_FN_NAME:ident, [$($PARAM:ident),+], $DOC:expr) => { |
| paste::paste! { |
| #[doc = " Create a [`WindowFunction`](datafusion_expr::Expr::WindowFunction) expression for"] |
| #[doc = concat!(" `", stringify!($UDWF), "` user-defined window function.")] |
| #[doc = ""] |
| #[doc = concat!(" ", $DOC)] |
| pub fn $OUT_FN_NAME( |
| $($PARAM: datafusion_expr::Expr),+ |
| ) -> datafusion_expr::Expr { |
| [<$OUT_FN_NAME _udwf>]() |
| .call(vec![$($PARAM),+]) |
| } |
| } |
| }; |
| } |
| |
| /// Defines a user-defined window function. |
| /// |
| /// Combines [`get_or_init_udwf!`] and [`create_udwf_expr!`] into a |
| /// single macro for convenience. |
| /// |
| /// # Arguments |
| /// |
| /// * `$UDWF`: The struct which defines the [`Signature`] of the |
| /// user-defined window function. |
| /// * `$OUT_FN_NAME`: The basename to generate a unique function name like |
| /// `$OUT_FN_NAME_udwf`. |
| /// * (optional) `[$($PARAM:ident),+]`: An array of 1 or more parameters |
| /// for the generated function. The type of parameters is [`Expr`]. |
| /// When omitted this creates a function with zero parameters. |
| /// * `$DOC`: Doc comments for UDWF. |
| /// * (optional) `$CTOR`: Pass a custom constructor. When omitted it |
| /// automatically resolves to `$UDWF::default()`. |
| /// |
| /// [`Signature`]: datafusion_expr::Signature |
| /// [`Expr`]: datafusion_expr::Expr |
| /// |
| /// # Usage |
| /// |
| /// ## Expression API With Zero parameters |
| /// 1. Uses default constructor for UDWF. |
| /// |
| /// ``` |
| /// # use std::any::Any; |
| /// use arrow::datatypes::FieldRef; |
| /// # use datafusion_common::arrow::datatypes::{DataType, Field}; |
| /// # use datafusion_expr::{PartitionEvaluator, Signature, Volatility, WindowUDFImpl}; |
| /// # |
| /// # use datafusion_functions_window_common::field::WindowUDFFieldArgs; |
| /// # use datafusion_functions_window::{define_udwf_and_expr, get_or_init_udwf, create_udwf_expr}; |
| /// # use datafusion_functions_window_common::partition::PartitionEvaluatorArgs; |
| /// # |
| /// /// 1. Defines the `simple_udwf()` user-defined window function. |
| /// /// |
| /// /// 2. Defines the expression API: |
| /// /// ``` |
| /// /// pub fn simple() -> datafusion_expr::Expr { |
| /// /// simple_udwf().call(vec![]) |
| /// /// } |
| /// /// ``` |
| /// define_udwf_and_expr!( |
| /// SimpleUDWF, |
| /// simple, |
| /// "a simple user-defined window function" |
| /// ); |
| /// # |
| /// # assert_eq!(simple_udwf().name(), "simple_user_defined_window_function"); |
| /// # |
| /// # #[derive(Debug, PartialEq, Eq, Hash)] |
| /// # struct SimpleUDWF { |
| /// # signature: Signature, |
| /// # } |
| /// # |
| /// # impl Default for SimpleUDWF { |
| /// # fn default() -> Self { |
| /// # Self { |
| /// # signature: Signature::any(0, Volatility::Immutable), |
| /// # } |
| /// # } |
| /// # } |
| /// # |
| /// # impl WindowUDFImpl for SimpleUDWF { |
| /// # fn as_any(&self) -> &dyn Any { |
| /// # self |
| /// # } |
| /// # fn name(&self) -> &str { |
| /// # "simple_user_defined_window_function" |
| /// # } |
| /// # fn signature(&self) -> &Signature { |
| /// # &self.signature |
| /// # } |
| /// # fn partition_evaluator( |
| /// # &self, |
| /// # partition_evaluator_args: PartitionEvaluatorArgs, |
| /// # ) -> datafusion_common::Result<Box<dyn PartitionEvaluator>> { |
| /// # unimplemented!() |
| /// # } |
| /// # fn field(&self, field_args: WindowUDFFieldArgs) -> datafusion_common::Result<FieldRef> { |
| /// # Ok(Field::new(field_args.name(), DataType::Int64, false).into()) |
| /// # } |
| /// # } |
| /// # |
| /// ``` |
| /// |
| /// 2. Uses a custom constructor for UDWF. |
| /// |
| /// ``` |
| /// # use std::any::Any; |
| /// use arrow::datatypes::FieldRef; |
| /// # use datafusion_common::arrow::datatypes::{DataType, Field}; |
| /// # use datafusion_expr::{PartitionEvaluator, Signature, Volatility, WindowUDFImpl}; |
| /// # use datafusion_functions_window::{create_udwf_expr, define_udwf_and_expr, get_or_init_udwf}; |
| /// # use datafusion_functions_window_common::field::WindowUDFFieldArgs; |
| /// # use datafusion_functions_window_common::partition::PartitionEvaluatorArgs; |
| /// # |
| /// /// 1. Defines the `row_number_udwf()` user-defined window function. |
| /// /// |
| /// /// 2. Defines the expression API: |
| /// /// ``` |
| /// /// pub fn row_number() -> datafusion_expr::Expr { |
| /// /// row_number_udwf().call(vec![]) |
| /// /// } |
| /// /// ``` |
| /// define_udwf_and_expr!( |
| /// RowNumber, |
| /// row_number, |
| /// "Returns a unique row number for each row in window partition beginning at 1.", |
| /// RowNumber::new // <-- custom constructor |
| /// ); |
| /// # |
| /// # assert_eq!( |
| /// # row_number().name_for_alias().unwrap(), |
| /// # "row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" |
| /// # ); |
| /// # |
| /// # #[derive(Debug, PartialEq, Eq, Hash)] |
| /// # struct RowNumber { |
| /// # signature: Signature, |
| /// # } |
| /// # impl RowNumber { |
| /// # fn new() -> Self { |
| /// # Self { |
| /// # signature: Signature::any(0, Volatility::Immutable), |
| /// # } |
| /// # } |
| /// # } |
| /// # impl WindowUDFImpl for RowNumber { |
| /// # fn as_any(&self) -> &dyn Any { |
| /// # self |
| /// # } |
| /// # fn name(&self) -> &str { |
| /// # "row_number" |
| /// # } |
| /// # fn signature(&self) -> &Signature { |
| /// # &self.signature |
| /// # } |
| /// # fn partition_evaluator( |
| /// # &self, |
| /// # _partition_evaluator_args: PartitionEvaluatorArgs, |
| /// # ) -> datafusion_common::Result<Box<dyn PartitionEvaluator>> { |
| /// # unimplemented!() |
| /// # } |
| /// # fn field(&self, field_args: WindowUDFFieldArgs) -> datafusion_common::Result<FieldRef> { |
| /// # Ok(Field::new(field_args.name(), DataType::UInt64, false).into()) |
| /// # } |
| /// # } |
| /// ``` |
| /// |
| /// ## Expression API With Multiple Parameters |
| /// 3. Uses default constructor for UDWF |
| /// |
| /// ``` |
| /// # use std::any::Any; |
| /// use arrow::datatypes::FieldRef; |
| /// # |
| /// # use datafusion_expr::{ |
| /// # PartitionEvaluator, Signature, TypeSignature, Volatility, WindowUDFImpl, |
| /// # }; |
| /// # |
| /// # use datafusion_functions_window::{create_udwf_expr, define_udwf_and_expr, get_or_init_udwf}; |
| /// # use datafusion_functions_window_common::field::WindowUDFFieldArgs; |
| /// # |
| /// # use datafusion_common::arrow::datatypes::Field; |
| /// # use datafusion_common::ScalarValue; |
| /// # use datafusion_expr::{col, lit}; |
| /// # use datafusion_functions_window_common::partition::PartitionEvaluatorArgs; |
| /// # |
| /// /// 1. Defines the `lead_udwf()` user-defined window function. |
| /// /// |
| /// /// 2. Defines the expression API: |
| /// /// ``` |
| /// /// pub fn lead( |
| /// /// expr: datafusion_expr::Expr, |
| /// /// offset: datafusion_expr::Expr, |
| /// /// default: datafusion_expr::Expr, |
| /// /// ) -> datafusion_expr::Expr { |
| /// /// lead_udwf().call(vec![expr, offset, default]) |
| /// /// } |
| /// /// ``` |
| /// define_udwf_and_expr!( |
| /// Lead, |
| /// lead, |
| /// [expr, offset, default], // <- 3 parameters |
| /// "user-defined window function" |
| /// ); |
| /// # |
| /// # assert_eq!( |
| /// # lead(col("a"), lit(1i64), lit(ScalarValue::Null)) |
| /// # .name_for_alias() |
| /// # .unwrap(), |
| /// # "lead(a,Int64(1),NULL) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" |
| /// # ); |
| /// # |
| /// # #[derive(Debug, PartialEq, Eq, Hash)] |
| /// # struct Lead { |
| /// # signature: Signature, |
| /// # } |
| /// # |
| /// # impl Default for Lead { |
| /// # fn default() -> Self { |
| /// # Self { |
| /// # signature: Signature::one_of( |
| /// # vec![ |
| /// # TypeSignature::Any(1), |
| /// # TypeSignature::Any(2), |
| /// # TypeSignature::Any(3), |
| /// # ], |
| /// # Volatility::Immutable, |
| /// # ), |
| /// # } |
| /// # } |
| /// # } |
| /// # |
| /// # impl WindowUDFImpl for Lead { |
| /// # fn as_any(&self) -> &dyn Any { |
| /// # self |
| /// # } |
| /// # fn name(&self) -> &str { |
| /// # "lead" |
| /// # } |
| /// # fn signature(&self) -> &Signature { |
| /// # &self.signature |
| /// # } |
| /// # fn partition_evaluator( |
| /// # &self, |
| /// # _partition_evaluator_args: PartitionEvaluatorArgs, |
| /// # ) -> datafusion_common::Result<Box<dyn PartitionEvaluator>> { |
| /// # unimplemented!() |
| /// # } |
| /// # fn field(&self, field_args: WindowUDFFieldArgs) -> datafusion_common::Result<FieldRef> { |
| /// # Ok(Field::new( |
| /// # field_args.name(), |
| /// # field_args.get_input_field(0).unwrap().data_type().clone(), |
| /// # false, |
| /// # ).into()) |
| /// # } |
| /// # } |
| /// ``` |
| /// 4. Uses custom constructor for UDWF |
| /// |
| /// ``` |
| /// # use std::any::Any; |
| /// use arrow::datatypes::FieldRef; |
| /// # |
| /// # use datafusion_expr::{ |
| /// # PartitionEvaluator, Signature, TypeSignature, Volatility, WindowUDFImpl, |
| /// # }; |
| /// # |
| /// # use datafusion_functions_window::{create_udwf_expr, define_udwf_and_expr, get_or_init_udwf}; |
| /// # use datafusion_functions_window_common::field::WindowUDFFieldArgs; |
| /// # |
| /// # use datafusion_common::arrow::datatypes::Field; |
| /// # use datafusion_common::ScalarValue; |
| /// # use datafusion_expr::{col, lit}; |
| /// # use datafusion_functions_window_common::partition::PartitionEvaluatorArgs; |
| /// # |
| /// /// 1. Defines the `lead_udwf()` user-defined window function. |
| /// /// |
| /// /// 2. Defines the expression API: |
| /// /// ``` |
| /// /// pub fn lead( |
| /// /// expr: datafusion_expr::Expr, |
| /// /// offset: datafusion_expr::Expr, |
| /// /// default: datafusion_expr::Expr, |
| /// /// ) -> datafusion_expr::Expr { |
| /// /// lead_udwf().call(vec![expr, offset, default]) |
| /// /// } |
| /// /// ``` |
| /// define_udwf_and_expr!( |
| /// Lead, |
| /// lead, |
| /// [expr, offset, default], // <- 3 parameters |
| /// "user-defined window function", |
| /// Lead::new // <- Custom constructor |
| /// ); |
| /// # |
| /// # assert_eq!( |
| /// # lead(col("a"), lit(1i64), lit(ScalarValue::Null)) |
| /// # .name_for_alias() |
| /// # .unwrap(), |
| /// # "lead(a,Int64(1),NULL) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" |
| /// # ); |
| /// # |
| /// # #[derive(Debug, PartialEq, Eq, Hash)] |
| /// # struct Lead { |
| /// # signature: Signature, |
| /// # } |
| /// # |
| /// # impl Lead { |
| /// # fn new() -> Self { |
| /// # Self { |
| /// # signature: Signature::one_of( |
| /// # vec![ |
| /// # TypeSignature::Any(1), |
| /// # TypeSignature::Any(2), |
| /// # TypeSignature::Any(3), |
| /// # ], |
| /// # Volatility::Immutable, |
| /// # ), |
| /// # } |
| /// # } |
| /// # } |
| /// # |
| /// # impl WindowUDFImpl for Lead { |
| /// # fn as_any(&self) -> &dyn Any { |
| /// # self |
| /// # } |
| /// # fn name(&self) -> &str { |
| /// # "lead" |
| /// # } |
| /// # fn signature(&self) -> &Signature { |
| /// # &self.signature |
| /// # } |
| /// # fn partition_evaluator( |
| /// # &self, |
| /// # _partition_evaluator_args: PartitionEvaluatorArgs, |
| /// # ) -> datafusion_common::Result<Box<dyn PartitionEvaluator>> { |
| /// # unimplemented!() |
| /// # } |
| /// # fn field(&self, field_args: WindowUDFFieldArgs) -> datafusion_common::Result<FieldRef> { |
| /// # Ok(Field::new( |
| /// # field_args.name(), |
| /// # field_args.get_input_field(0).unwrap().data_type().clone(), |
| /// # false, |
| /// # ).into()) |
| /// # } |
| /// # } |
| /// ``` |
| #[macro_export] |
| macro_rules! define_udwf_and_expr { |
| // Defines UDWF with default constructor |
| // Defines expression API with zero parameters |
| ($UDWF:ident, $OUT_FN_NAME:ident, $DOC:expr) => { |
| get_or_init_udwf!($UDWF, $OUT_FN_NAME, $DOC); |
| create_udwf_expr!($UDWF, $OUT_FN_NAME, $DOC); |
| }; |
| |
| // Defines UDWF by passing a custom constructor |
| // Defines expression API with zero parameters |
| ($UDWF:ident, $OUT_FN_NAME:ident, $DOC:expr, $CTOR:path) => { |
| get_or_init_udwf!($UDWF, $OUT_FN_NAME, $DOC, $CTOR); |
| create_udwf_expr!($UDWF, $OUT_FN_NAME, $DOC); |
| }; |
| |
| // Defines UDWF with default constructor |
| // Defines expression API with multiple parameters |
| ($UDWF:ident, $OUT_FN_NAME:ident, [$($PARAM:ident),+], $DOC:expr) => { |
| get_or_init_udwf!($UDWF, $OUT_FN_NAME, $DOC); |
| create_udwf_expr!($UDWF, $OUT_FN_NAME, [$($PARAM),+], $DOC); |
| }; |
| |
| // Defines UDWF by passing a custom constructor |
| // Defines expression API with multiple parameters |
| ($UDWF:ident, $OUT_FN_NAME:ident, [$($PARAM:ident),+], $DOC:expr, $CTOR:path) => { |
| get_or_init_udwf!($UDWF, $OUT_FN_NAME, $DOC, $CTOR); |
| create_udwf_expr!($UDWF, $OUT_FN_NAME, [$($PARAM),+], $DOC); |
| }; |
| } |