Skip to content

Commit f54712d

Browse files
authored
handle 0 and NULL value of NTH_VALUE function (#12676)
* handle 0 and NULL value of NTH_VALUE function * use exec_err * cargo fmt
1 parent 2c2e0e7 commit f54712d

File tree

3 files changed

+61
-25
lines changed

3 files changed

+61
-25
lines changed

datafusion/physical-expr/src/window/nth_value.rs

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::PhysicalExpr;
3030
use arrow::array::{Array, ArrayRef};
3131
use arrow::datatypes::{DataType, Field};
3232
use datafusion_common::Result;
33-
use datafusion_common::{exec_err, ScalarValue};
33+
use datafusion_common::ScalarValue;
3434
use datafusion_expr::window_state::WindowAggState;
3535
use datafusion_expr::PartitionEvaluator;
3636

@@ -86,16 +86,13 @@ impl NthValue {
8686
n: i64,
8787
ignore_nulls: bool,
8888
) -> Result<Self> {
89-
match n {
90-
0 => exec_err!("NTH_VALUE expects n to be non-zero"),
91-
_ => Ok(Self {
92-
name: name.into(),
93-
expr,
94-
data_type,
95-
kind: NthValueKind::Nth(n),
96-
ignore_nulls,
97-
}),
98-
}
89+
Ok(Self {
90+
name: name.into(),
91+
expr,
92+
data_type,
93+
kind: NthValueKind::Nth(n),
94+
ignore_nulls,
95+
})
9996
}
10097

10198
/// Get the NTH_VALUE kind
@@ -188,10 +185,7 @@ impl PartitionEvaluator for NthValueEvaluator {
188185
// Negative index represents reverse direction.
189186
(n_range >= reverse_index, true)
190187
}
191-
Ordering::Equal => {
192-
// The case n = 0 is not valid for the NTH_VALUE function.
193-
unreachable!();
194-
}
188+
Ordering::Equal => (true, false),
195189
}
196190
}
197191
};
@@ -298,10 +292,7 @@ impl PartitionEvaluator for NthValueEvaluator {
298292
)
299293
}
300294
}
301-
Ordering::Equal => {
302-
// The case n = 0 is not valid for the NTH_VALUE function.
303-
unreachable!();
304-
}
295+
Ordering::Equal => ScalarValue::try_from(arr.data_type()),
305296
}
306297
}
307298
}

datafusion/physical-plan/src/windows/mod.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,20 +185,26 @@ fn get_scalar_value_from_args(
185185
}
186186

187187
fn get_signed_integer(value: ScalarValue) -> Result<i64> {
188+
if value.is_null() {
189+
return Ok(0);
190+
}
191+
188192
if !value.data_type().is_integer() {
189-
return Err(DataFusionError::Execution(
190-
"Expected an integer value".to_string(),
191-
));
193+
return exec_err!("Expected an integer value");
192194
}
195+
193196
value.cast_to(&DataType::Int64)?.try_into()
194197
}
195198

196199
fn get_unsigned_integer(value: ScalarValue) -> Result<u64> {
200+
if value.is_null() {
201+
return Ok(0);
202+
}
203+
197204
if !value.data_type().is_integer() {
198-
return Err(DataFusionError::Execution(
199-
"Expected an integer value".to_string(),
200-
));
205+
return exec_err!("Expected an integer value");
201206
}
207+
202208
value.cast_to(&DataType::UInt64)?.try_into()
203209
}
204210

datafusion/sqllogictest/test_files/window.slt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4894,3 +4894,42 @@ NULL a4 5
48944894

48954895
statement ok
48964896
drop table t
4897+
4898+
## test handle NULL and 0 value of nth_value
4899+
statement ok
4900+
CREATE TABLE t(v1 int, v2 int);
4901+
4902+
statement ok
4903+
INSERT INTO t VALUES (1,1), (1,2),(1,3),(2,1),(2,2);
4904+
4905+
query II
4906+
SELECT v1, NTH_VALUE(v2, null) OVER (PARTITION BY v1 ORDER BY v2) FROM t;
4907+
----
4908+
1 NULL
4909+
1 NULL
4910+
1 NULL
4911+
2 NULL
4912+
2 NULL
4913+
4914+
query II
4915+
SELECT v1, NTH_VALUE(v2, v2*null) OVER (PARTITION BY v1 ORDER BY v2) FROM t;
4916+
----
4917+
1 NULL
4918+
1 NULL
4919+
1 NULL
4920+
2 NULL
4921+
2 NULL
4922+
4923+
query II
4924+
SELECT v1, NTH_VALUE(v2, 0) OVER (PARTITION BY v1 ORDER BY v2) FROM t;
4925+
----
4926+
1 NULL
4927+
1 NULL
4928+
1 NULL
4929+
2 NULL
4930+
2 NULL
4931+
4932+
statement ok
4933+
DROP TABLE t;
4934+
4935+
## end test handle NULL and 0 of NTH_VALUE

0 commit comments

Comments
 (0)