This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git
The following commit(s) were added to refs/heads/main by this push:
new a4e6b075b8 feat: Convert CumeDist to UDWF (#13051)
a4e6b075b8 is described below
commit a4e6b075b8fe448e0f1fde948626d7c43c1d9c4a
Author: Jonathan Chen <[email protected]>
AuthorDate: Wed Oct 23 07:00:20 2024 -0400
feat: Convert CumeDist to UDWF (#13051)
* Transferred cumedist
* fixes
* remove expr tests
* small fix
* small fix
* check
* clippy fix
* roundtrip fix
---
datafusion/expr/src/built_in_window_function.rs | 6 -
datafusion/expr/src/expr.rs | 23 +--
datafusion/expr/src/window_function.rs | 5 -
datafusion/functions-window/src/cume_dist.rs | 170 +++++++++++++++++++++
datafusion/functions-window/src/lib.rs | 3 +
datafusion/physical-expr/src/expressions/mod.rs | 1 -
datafusion/physical-expr/src/window/cume_dist.rs | 145 ------------------
datafusion/physical-expr/src/window/mod.rs | 1 -
datafusion/physical-plan/src/windows/mod.rs | 3 +-
datafusion/proto/proto/datafusion.proto | 2 +-
datafusion/proto/src/generated/pbjson.rs | 3 -
datafusion/proto/src/generated/prost.rs | 4 +-
datafusion/proto/src/logical_plan/from_proto.rs | 1 -
datafusion/proto/src/logical_plan/to_proto.rs | 1 -
datafusion/proto/src/physical_plan/to_proto.rs | 10 +-
.../proto/tests/cases/roundtrip_logical_plan.rs | 3 +-
datafusion/sqllogictest/test_files/window.slt | 4 +-
docs/source/user-guide/sql/window_functions_new.md | 9 ++
18 files changed, 195 insertions(+), 199 deletions(-)
diff --git a/datafusion/expr/src/built_in_window_function.rs
b/datafusion/expr/src/built_in_window_function.rs
index 2c70a07a4e..36916a6b59 100644
--- a/datafusion/expr/src/built_in_window_function.rs
+++ b/datafusion/expr/src/built_in_window_function.rs
@@ -40,8 +40,6 @@ impl fmt::Display for BuiltInWindowFunction {
/// [Window Function]: https://en.wikipedia.org/wiki/Window_function_(SQL)
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash, EnumIter)]
pub enum BuiltInWindowFunction {
- /// Relative rank of the current row: (number of rows preceding or peer
with current row) / (total rows)
- CumeDist,
/// Integer ranging from 1 to the argument value, dividing the partition
as equally as possible
Ntile,
/// returns value evaluated at the row that is the first row of the window
frame
@@ -56,7 +54,6 @@ impl BuiltInWindowFunction {
pub fn name(&self) -> &str {
use BuiltInWindowFunction::*;
match self {
- CumeDist => "CUME_DIST",
Ntile => "NTILE",
FirstValue => "first_value",
LastValue => "last_value",
@@ -69,7 +66,6 @@ impl FromStr for BuiltInWindowFunction {
type Err = DataFusionError;
fn from_str(name: &str) -> Result<BuiltInWindowFunction> {
Ok(match name.to_uppercase().as_str() {
- "CUME_DIST" => BuiltInWindowFunction::CumeDist,
"NTILE" => BuiltInWindowFunction::Ntile,
"FIRST_VALUE" => BuiltInWindowFunction::FirstValue,
"LAST_VALUE" => BuiltInWindowFunction::LastValue,
@@ -102,7 +98,6 @@ impl BuiltInWindowFunction {
match self {
BuiltInWindowFunction::Ntile => Ok(DataType::UInt64),
- BuiltInWindowFunction::CumeDist => Ok(DataType::Float64),
BuiltInWindowFunction::FirstValue
| BuiltInWindowFunction::LastValue
| BuiltInWindowFunction::NthValue =>
Ok(input_expr_types[0].clone()),
@@ -113,7 +108,6 @@ impl BuiltInWindowFunction {
pub fn signature(&self) -> Signature {
// Note: The physical expression must accept the type returned by this
function or the execution panics.
match self {
- BuiltInWindowFunction::CumeDist => Signature::any(0,
Volatility::Immutable),
BuiltInWindowFunction::FirstValue |
BuiltInWindowFunction::LastValue => {
Signature::any(1, Volatility::Immutable)
}
diff --git a/datafusion/expr/src/expr.rs b/datafusion/expr/src/expr.rs
index 691b65d344..7fadf6391b 100644
--- a/datafusion/expr/src/expr.rs
+++ b/datafusion/expr/src/expr.rs
@@ -2567,15 +2567,6 @@ mod test {
Ok(())
}
- #[test]
- fn test_cume_dist_return_type() -> Result<()> {
- let fun = find_df_window_func("cume_dist").unwrap();
- let observed = fun.return_type(&[], &[], "")?;
- assert_eq!(DataType::Float64, observed);
-
- Ok(())
- }
-
#[test]
fn test_ntile_return_type() -> Result<()> {
let fun = find_df_window_func("ntile").unwrap();
@@ -2587,13 +2578,7 @@ mod test {
#[test]
fn test_window_function_case_insensitive() -> Result<()> {
- let names = vec![
- "cume_dist",
- "ntile",
- "first_value",
- "last_value",
- "nth_value",
- ];
+ let names = vec!["ntile", "first_value", "last_value", "nth_value"];
for name in names {
let fun = find_df_window_func(name).unwrap();
let fun2 =
find_df_window_func(name.to_uppercase().as_str()).unwrap();
@@ -2609,12 +2594,6 @@ mod test {
#[test]
fn test_find_df_window_function() {
- assert_eq!(
- find_df_window_func("cume_dist"),
- Some(WindowFunctionDefinition::BuiltInWindowFunction(
- built_in_window_function::BuiltInWindowFunction::CumeDist
- ))
- );
assert_eq!(
find_df_window_func("first_value"),
Some(WindowFunctionDefinition::BuiltInWindowFunction(
diff --git a/datafusion/expr/src/window_function.rs
b/datafusion/expr/src/window_function.rs
index 3e1870c59c..c13a028e4a 100644
--- a/datafusion/expr/src/window_function.rs
+++ b/datafusion/expr/src/window_function.rs
@@ -17,11 +17,6 @@
use crate::{expr::WindowFunction, BuiltInWindowFunction, Expr, Literal};
-/// Create an expression to represent the `cume_dist` window function
-pub fn cume_dist() -> Expr {
- Expr::WindowFunction(WindowFunction::new(BuiltInWindowFunction::CumeDist,
vec![]))
-}
-
/// Create an expression to represent the `ntile` window function
pub fn ntile(arg: Expr) -> Expr {
Expr::WindowFunction(WindowFunction::new(BuiltInWindowFunction::Ntile,
vec![arg]))
diff --git a/datafusion/functions-window/src/cume_dist.rs
b/datafusion/functions-window/src/cume_dist.rs
new file mode 100644
index 0000000000..9e30c672fe
--- /dev/null
+++ b/datafusion/functions-window/src/cume_dist.rs
@@ -0,0 +1,170 @@
+// 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.
+
+//! `cume_dist` window function implementation
+
+use datafusion_common::arrow::array::{ArrayRef, Float64Array};
+use datafusion_common::arrow::datatypes::DataType;
+use datafusion_common::arrow::datatypes::Field;
+use datafusion_common::Result;
+use datafusion_expr::window_doc_sections::DOC_SECTION_RANKING;
+use datafusion_expr::{
+ Documentation, PartitionEvaluator, Signature, Volatility, WindowUDFImpl,
+};
+use datafusion_functions_window_common::field;
+use datafusion_functions_window_common::partition::PartitionEvaluatorArgs;
+use field::WindowUDFFieldArgs;
+use std::any::Any;
+use std::fmt::Debug;
+use std::iter;
+use std::ops::Range;
+use std::sync::{Arc, OnceLock};
+
+define_udwf_and_expr!(
+ CumeDist,
+ cume_dist,
+ "Calculates the cumulative distribution of a value in a group of values."
+);
+
+/// CumeDist calculates the cume_dist in the window function with order by
+#[derive(Debug)]
+pub struct CumeDist {
+ signature: Signature,
+}
+
+impl CumeDist {
+ pub fn new() -> Self {
+ Self {
+ signature: Signature::any(0, Volatility::Immutable),
+ }
+ }
+}
+
+impl Default for CumeDist {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl WindowUDFImpl for CumeDist {
+ /// Return a reference to Any that can be used for downcasting
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+
+ fn name(&self) -> &str {
+ "cume_dist"
+ }
+
+ fn signature(&self) -> &Signature {
+ &self.signature
+ }
+
+ fn partition_evaluator(
+ &self,
+ _partition_evaluator_args: PartitionEvaluatorArgs,
+ ) -> Result<Box<dyn PartitionEvaluator>> {
+ Ok(Box::<CumeDistEvaluator>::default())
+ }
+
+ fn field(&self, field_args: WindowUDFFieldArgs) -> Result<Field> {
+ Ok(Field::new(field_args.name(), DataType::Float64, false))
+ }
+
+ fn documentation(&self) -> Option<&Documentation> {
+ Some(get_cume_dist_doc())
+ }
+}
+
+static DOCUMENTATION: OnceLock<Documentation> = OnceLock::new();
+
+fn get_cume_dist_doc() -> &'static Documentation {
+ DOCUMENTATION.get_or_init(|| {
+ Documentation::builder()
+ .with_doc_section(DOC_SECTION_RANKING)
+ .with_description(
+ "Relative rank of the current row: (number of rows preceding
or peer with current row) / (total rows).",
+ )
+ .with_syntax_example("cume_dist()")
+ .build()
+ .unwrap()
+ })
+}
+
+#[derive(Debug, Default)]
+pub(crate) struct CumeDistEvaluator;
+
+impl PartitionEvaluator for CumeDistEvaluator {
+ /// Computes the cumulative distribution for all rows in the partition
+ fn evaluate_all_with_rank(
+ &self,
+ num_rows: usize,
+ ranks_in_partition: &[Range<usize>],
+ ) -> Result<ArrayRef> {
+ let scalar = num_rows as f64;
+ let result = Float64Array::from_iter_values(
+ ranks_in_partition
+ .iter()
+ .scan(0_u64, |acc, range| {
+ let len = range.end - range.start;
+ *acc += len as u64;
+ let value: f64 = (*acc as f64) / scalar;
+ let result = iter::repeat(value).take(len);
+ Some(result)
+ })
+ .flatten(),
+ );
+ Ok(Arc::new(result))
+ }
+
+ fn include_rank(&self) -> bool {
+ true
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use datafusion_common::cast::as_float64_array;
+
+ fn test_f64_result(
+ num_rows: usize,
+ ranks: Vec<Range<usize>>,
+ expected: Vec<f64>,
+ ) -> Result<()> {
+ let evaluator = CumeDistEvaluator;
+ let result = evaluator.evaluate_all_with_rank(num_rows, &ranks)?;
+ let result = as_float64_array(&result)?;
+ let result = result.values().to_vec();
+ assert_eq!(expected, result);
+ Ok(())
+ }
+
+ #[test]
+ #[allow(clippy::single_range_in_vec_init)]
+ fn test_cume_dist() -> Result<()> {
+ test_f64_result(0, vec![], vec![])?;
+
+ test_f64_result(1, vec![0..1], vec![1.0])?;
+
+ test_f64_result(2, vec![0..2], vec![1.0, 1.0])?;
+
+ test_f64_result(4, vec![0..2, 2..4], vec![0.5, 0.5, 1.0, 1.0])?;
+
+ Ok(())
+ }
+}
diff --git a/datafusion/functions-window/src/lib.rs
b/datafusion/functions-window/src/lib.rs
index 5a2aafa289..13a77977d5 100644
--- a/datafusion/functions-window/src/lib.rs
+++ b/datafusion/functions-window/src/lib.rs
@@ -32,6 +32,7 @@ use datafusion_expr::WindowUDF;
#[macro_use]
pub mod macros;
+pub mod cume_dist;
pub mod lead_lag;
pub mod rank;
@@ -40,6 +41,7 @@ mod utils;
/// Fluent-style API for creating `Expr`s
pub mod expr_fn {
+ pub use super::cume_dist::cume_dist;
pub use super::lead_lag::lag;
pub use super::lead_lag::lead;
pub use super::rank::{dense_rank, percent_rank, rank};
@@ -49,6 +51,7 @@ pub mod expr_fn {
/// Returns all default window functions
pub fn all_default_window_functions() -> Vec<Arc<WindowUDF>> {
vec![
+ cume_dist::cume_dist_udwf(),
row_number::row_number_udwf(),
lead_lag::lead_udwf(),
lead_lag::lag_udwf(),
diff --git a/datafusion/physical-expr/src/expressions/mod.rs
b/datafusion/physical-expr/src/expressions/mod.rs
index 54b8aafdb4..63047f6929 100644
--- a/datafusion/physical-expr/src/expressions/mod.rs
+++ b/datafusion/physical-expr/src/expressions/mod.rs
@@ -35,7 +35,6 @@ mod unknown_column;
/// Module with some convenient methods used in expression building
pub use crate::aggregate::stats::StatsType;
-pub use crate::window::cume_dist::{cume_dist, CumeDist};
pub use crate::window::nth_value::NthValue;
pub use crate::window::ntile::Ntile;
pub use crate::PhysicalSortExpr;
diff --git a/datafusion/physical-expr/src/window/cume_dist.rs
b/datafusion/physical-expr/src/window/cume_dist.rs
deleted file mode 100644
index 9720187ea8..0000000000
--- a/datafusion/physical-expr/src/window/cume_dist.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-// 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.
-
-//! Defines physical expression for `cume_dist` that can evaluated
-//! at runtime during query execution
-
-use crate::window::BuiltInWindowFunctionExpr;
-use crate::PhysicalExpr;
-use arrow::array::ArrayRef;
-use arrow::array::Float64Array;
-use arrow::datatypes::{DataType, Field};
-use datafusion_common::Result;
-use datafusion_expr::PartitionEvaluator;
-use std::any::Any;
-use std::iter;
-use std::ops::Range;
-use std::sync::Arc;
-
-/// CumeDist calculates the cume_dist in the window function with order by
-#[derive(Debug)]
-pub struct CumeDist {
- name: String,
- /// Output data type
- data_type: DataType,
-}
-
-/// Create a cume_dist window function
-pub fn cume_dist(name: String, data_type: &DataType) -> CumeDist {
- CumeDist {
- name,
- data_type: data_type.clone(),
- }
-}
-
-impl BuiltInWindowFunctionExpr for CumeDist {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
- fn field(&self) -> Result<Field> {
- let nullable = false;
- Ok(Field::new(self.name(), self.data_type.clone(), nullable))
- }
-
- fn expressions(&self) -> Vec<Arc<dyn PhysicalExpr>> {
- vec![]
- }
-
- fn name(&self) -> &str {
- &self.name
- }
-
- fn create_evaluator(&self) -> Result<Box<dyn PartitionEvaluator>> {
- Ok(Box::new(CumeDistEvaluator {}))
- }
-}
-
-#[derive(Debug)]
-pub(crate) struct CumeDistEvaluator;
-
-impl PartitionEvaluator for CumeDistEvaluator {
- fn evaluate_all_with_rank(
- &self,
- num_rows: usize,
- ranks_in_partition: &[Range<usize>],
- ) -> Result<ArrayRef> {
- let scalar = num_rows as f64;
- let result = Float64Array::from_iter_values(
- ranks_in_partition
- .iter()
- .scan(0_u64, |acc, range| {
- let len = range.end - range.start;
- *acc += len as u64;
- let value: f64 = (*acc as f64) / scalar;
- let result = iter::repeat(value).take(len);
- Some(result)
- })
- .flatten(),
- );
- Ok(Arc::new(result))
- }
-
- fn include_rank(&self) -> bool {
- true
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use datafusion_common::cast::as_float64_array;
-
- fn test_i32_result(
- expr: &CumeDist,
- num_rows: usize,
- ranks: Vec<Range<usize>>,
- expected: Vec<f64>,
- ) -> Result<()> {
- let result = expr
- .create_evaluator()?
- .evaluate_all_with_rank(num_rows, &ranks)?;
- let result = as_float64_array(&result)?;
- let result = result.values();
- assert_eq!(expected, *result);
- Ok(())
- }
-
- #[test]
- #[allow(clippy::single_range_in_vec_init)]
- fn test_cume_dist() -> Result<()> {
- let r = cume_dist("arr".into(), &DataType::Float64);
-
- let expected = vec![0.0; 0];
- test_i32_result(&r, 0, vec![], expected)?;
-
- let expected = vec![1.0; 1];
- test_i32_result(&r, 1, vec![0..1], expected)?;
-
- let expected = vec![1.0; 2];
- test_i32_result(&r, 2, vec![0..2], expected)?;
-
- let expected = vec![0.5, 0.5, 1.0, 1.0];
- test_i32_result(&r, 4, vec![0..2, 2..4], expected)?;
-
- let expected = vec![0.25, 0.5, 0.75, 1.0];
- test_i32_result(&r, 4, vec![0..1, 1..2, 2..3, 3..4], expected)?;
-
- Ok(())
- }
-}
diff --git a/datafusion/physical-expr/src/window/mod.rs
b/datafusion/physical-expr/src/window/mod.rs
index c0fe3c2933..7bab4dbc5a 100644
--- a/datafusion/physical-expr/src/window/mod.rs
+++ b/datafusion/physical-expr/src/window/mod.rs
@@ -18,7 +18,6 @@
mod aggregate;
mod built_in;
mod built_in_window_function_expr;
-pub(crate) mod cume_dist;
pub(crate) mod nth_value;
pub(crate) mod ntile;
mod sliding_aggregate;
diff --git a/datafusion/physical-plan/src/windows/mod.rs
b/datafusion/physical-plan/src/windows/mod.rs
index f6902fcbe2..39ff71496e 100644
--- a/datafusion/physical-plan/src/windows/mod.rs
+++ b/datafusion/physical-plan/src/windows/mod.rs
@@ -21,7 +21,7 @@ use std::borrow::Borrow;
use std::sync::Arc;
use crate::{
- expressions::{cume_dist, Literal, NthValue, Ntile, PhysicalSortExpr},
+ expressions::{Literal, NthValue, Ntile, PhysicalSortExpr},
ExecutionPlan, ExecutionPlanProperties, InputOrderMode, PhysicalExpr,
};
@@ -219,7 +219,6 @@ fn create_built_in_window_expr(
let out_data_type: &DataType =
input_schema.field_with_name(&name)?.data_type();
Ok(match fun {
- BuiltInWindowFunction::CumeDist => Arc::new(cume_dist(name,
out_data_type)),
BuiltInWindowFunction::Ntile => {
let n = get_scalar_value_from_args(args, 0)?.ok_or_else(|| {
DataFusionError::Execution(
diff --git a/datafusion/proto/proto/datafusion.proto
b/datafusion/proto/proto/datafusion.proto
index a15fa2c5f9..c92328278e 100644
--- a/datafusion/proto/proto/datafusion.proto
+++ b/datafusion/proto/proto/datafusion.proto
@@ -511,7 +511,7 @@ enum BuiltInWindowFunction {
// RANK = 1;
// DENSE_RANK = 2;
// PERCENT_RANK = 3;
- CUME_DIST = 4;
+ // CUME_DIST = 4;
NTILE = 5;
// LAG = 6;
// LEAD = 7;
diff --git a/datafusion/proto/src/generated/pbjson.rs
b/datafusion/proto/src/generated/pbjson.rs
index d223e3646b..ca331cdaa5 100644
--- a/datafusion/proto/src/generated/pbjson.rs
+++ b/datafusion/proto/src/generated/pbjson.rs
@@ -1662,7 +1662,6 @@ impl serde::Serialize for BuiltInWindowFunction {
{
let variant = match self {
Self::Unspecified => "UNSPECIFIED",
- Self::CumeDist => "CUME_DIST",
Self::Ntile => "NTILE",
Self::FirstValue => "FIRST_VALUE",
Self::LastValue => "LAST_VALUE",
@@ -1679,7 +1678,6 @@ impl<'de> serde::Deserialize<'de> for
BuiltInWindowFunction {
{
const FIELDS: &[&str] = &[
"UNSPECIFIED",
- "CUME_DIST",
"NTILE",
"FIRST_VALUE",
"LAST_VALUE",
@@ -1725,7 +1723,6 @@ impl<'de> serde::Deserialize<'de> for
BuiltInWindowFunction {
{
match value {
"UNSPECIFIED" => Ok(BuiltInWindowFunction::Unspecified),
- "CUME_DIST" => Ok(BuiltInWindowFunction::CumeDist),
"NTILE" => Ok(BuiltInWindowFunction::Ntile),
"FIRST_VALUE" => Ok(BuiltInWindowFunction::FirstValue),
"LAST_VALUE" => Ok(BuiltInWindowFunction::LastValue),
diff --git a/datafusion/proto/src/generated/prost.rs
b/datafusion/proto/src/generated/prost.rs
index 6b234be57a..fb0b3bcb2c 100644
--- a/datafusion/proto/src/generated/prost.rs
+++ b/datafusion/proto/src/generated/prost.rs
@@ -1818,7 +1818,7 @@ pub enum BuiltInWindowFunction {
/// RANK = 1;
/// DENSE_RANK = 2;
/// PERCENT_RANK = 3;
- CumeDist = 4,
+ /// CUME_DIST = 4;
Ntile = 5,
/// LAG = 6;
/// LEAD = 7;
@@ -1834,7 +1834,6 @@ impl BuiltInWindowFunction {
pub fn as_str_name(&self) -> &'static str {
match self {
Self::Unspecified => "UNSPECIFIED",
- Self::CumeDist => "CUME_DIST",
Self::Ntile => "NTILE",
Self::FirstValue => "FIRST_VALUE",
Self::LastValue => "LAST_VALUE",
@@ -1845,7 +1844,6 @@ impl BuiltInWindowFunction {
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"UNSPECIFIED" => Some(Self::Unspecified),
- "CUME_DIST" => Some(Self::CumeDist),
"NTILE" => Some(Self::Ntile),
"FIRST_VALUE" => Some(Self::FirstValue),
"LAST_VALUE" => Some(Self::LastValue),
diff --git a/datafusion/proto/src/logical_plan/from_proto.rs
b/datafusion/proto/src/logical_plan/from_proto.rs
index 99b11939e9..4587c090c9 100644
--- a/datafusion/proto/src/logical_plan/from_proto.rs
+++ b/datafusion/proto/src/logical_plan/from_proto.rs
@@ -152,7 +152,6 @@ impl From<protobuf::BuiltInWindowFunction> for
BuiltInWindowFunction {
match built_in_function {
protobuf::BuiltInWindowFunction::Unspecified => todo!(),
protobuf::BuiltInWindowFunction::FirstValue => Self::FirstValue,
- protobuf::BuiltInWindowFunction::CumeDist => Self::CumeDist,
protobuf::BuiltInWindowFunction::Ntile => Self::Ntile,
protobuf::BuiltInWindowFunction::NthValue => Self::NthValue,
protobuf::BuiltInWindowFunction::LastValue => Self::LastValue,
diff --git a/datafusion/proto/src/logical_plan/to_proto.rs
b/datafusion/proto/src/logical_plan/to_proto.rs
index a34a220e49..dce0cd741f 100644
--- a/datafusion/proto/src/logical_plan/to_proto.rs
+++ b/datafusion/proto/src/logical_plan/to_proto.rs
@@ -128,7 +128,6 @@ impl From<&BuiltInWindowFunction> for
protobuf::BuiltInWindowFunction {
BuiltInWindowFunction::LastValue => Self::LastValue,
BuiltInWindowFunction::NthValue => Self::NthValue,
BuiltInWindowFunction::Ntile => Self::Ntile,
- BuiltInWindowFunction::CumeDist => Self::CumeDist,
}
}
}
diff --git a/datafusion/proto/src/physical_plan/to_proto.rs
b/datafusion/proto/src/physical_plan/to_proto.rs
index 33eca07231..37ea6a2b47 100644
--- a/datafusion/proto/src/physical_plan/to_proto.rs
+++ b/datafusion/proto/src/physical_plan/to_proto.rs
@@ -23,8 +23,8 @@ use datafusion::datasource::file_format::parquet::ParquetSink;
use datafusion::physical_expr::window::{NthValueKind,
SlidingAggregateWindowExpr};
use datafusion::physical_expr::{PhysicalSortExpr, ScalarFunctionExpr};
use datafusion::physical_plan::expressions::{
- BinaryExpr, CaseExpr, CastExpr, Column, CumeDist, InListExpr,
IsNotNullExpr,
- IsNullExpr, Literal, NegativeExpr, NotExpr, NthValue, Ntile, TryCastExpr,
+ BinaryExpr, CaseExpr, CastExpr, Column, InListExpr, IsNotNullExpr,
IsNullExpr,
+ Literal, NegativeExpr, NotExpr, NthValue, Ntile, TryCastExpr,
};
use datafusion::physical_plan::udaf::AggregateFunctionExpr;
use datafusion::physical_plan::windows::{BuiltInWindowExpr,
PlainAggregateWindowExpr};
@@ -108,9 +108,9 @@ pub fn serialize_physical_window_expr(
let expr = built_in_window_expr.get_built_in_func_expr();
let built_in_fn_expr = expr.as_any();
- let builtin_fn = if
built_in_fn_expr.downcast_ref::<CumeDist>().is_some() {
- protobuf::BuiltInWindowFunction::CumeDist
- } else if let Some(ntile_expr) =
built_in_fn_expr.downcast_ref::<Ntile>() {
+ let builtin_fn = if let Some(ntile_expr) =
+ built_in_fn_expr.downcast_ref::<Ntile>()
+ {
args.insert(
0,
Arc::new(Literal::new(datafusion_common::ScalarValue::Int64(Some(
diff --git a/datafusion/proto/tests/cases/roundtrip_logical_plan.rs
b/datafusion/proto/tests/cases/roundtrip_logical_plan.rs
index c017395d97..a8c82ff80f 100644
--- a/datafusion/proto/tests/cases/roundtrip_logical_plan.rs
+++ b/datafusion/proto/tests/cases/roundtrip_logical_plan.rs
@@ -48,7 +48,7 @@ use datafusion::functions_aggregate::expr_fn::{
use datafusion::functions_aggregate::min_max::max_udaf;
use datafusion::functions_nested::map::map;
use datafusion::functions_window::expr_fn::{
- dense_rank, lag, lead, percent_rank, rank, row_number,
+ cume_dist, dense_rank, lag, lead, percent_rank, rank, row_number,
};
use datafusion::functions_window::rank::rank_udwf;
use datafusion::prelude::*;
@@ -940,6 +940,7 @@ async fn roundtrip_expr_api() -> Result<()> {
vec![lit(1), lit(2), lit(3)],
vec![lit(10), lit(20), lit(30)],
),
+ cume_dist(),
row_number(),
rank(),
dense_rank(),
diff --git a/datafusion/sqllogictest/test_files/window.slt
b/datafusion/sqllogictest/test_files/window.slt
index b3f2786d3d..51e8592755 100644
--- a/datafusion/sqllogictest/test_files/window.slt
+++ b/datafusion/sqllogictest/test_files/window.slt
@@ -1135,8 +1135,8 @@ SELECT
query IRR
SELECT
c8,
- CUME_DIST() OVER(ORDER BY c9) as cd1,
- CUME_DIST() OVER(ORDER BY c9 ROWS BETWEEN 10 PRECEDING and 1 FOLLOWING) as
cd2
+ cume_dist() OVER(ORDER BY c9) as cd1,
+ cume_dist() OVER(ORDER BY c9 ROWS BETWEEN 10 PRECEDING and 1 FOLLOWING) as
cd2
FROM aggregate_test_100
ORDER BY c8
LIMIT 5
diff --git a/docs/source/user-guide/sql/window_functions_new.md
b/docs/source/user-guide/sql/window_functions_new.md
index 462fc900d1..89ce2284a7 100644
--- a/docs/source/user-guide/sql/window_functions_new.md
+++ b/docs/source/user-guide/sql/window_functions_new.md
@@ -157,11 +157,20 @@ All [aggregate functions](aggregate_functions.md) can be
used as window function
## Ranking Functions
+- [cume_dist](#cume_dist)
- [dense_rank](#dense_rank)
- [percent_rank](#percent_rank)
- [rank](#rank)
- [row_number](#row_number)
+### `cume_dist`
+
+Relative rank of the current row: (number of rows preceding or peer with
current row) / (total rows).
+
+```
+cume_dist()
+```
+
### `dense_rank`
Returns the rank of the current row without gaps. This function ranks rows in
a dense manner, meaning consecutive ranks are assigned even for identical
values.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]