Skip to content

Commit c48e993

Browse files
authored
Return None for cardinality overflow (#22309)
## Which issue does this PR close? Closes #22232 (cc @Dandandan ) ## Rationale for this change Prevent `Interval::cardinality()` from overflowing on the full `i64` range. ## What changes are included in this PR? - use `checked_add(1)` instead of `+ 1` - add a regression test for the full `i64` range ## Are these changes tested? - `cargo fmt --all --check` - `cargo test -p datafusion-expr-common test_cardinality_full_i64_range_does_not_overflow --lib` - `cargo clippy --all-targets --all-features -- -D warnings` could not run locally because `cmake` is not installed ## Are there any user-facing changes? - No
1 parent c3f3b7a commit c48e993

2 files changed

Lines changed: 22 additions & 1 deletion

File tree

datafusion/expr-common/src/interval_arithmetic.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ impl Interval {
944944
// Cardinality calculations are not implemented for this data type yet:
945945
None
946946
}
947-
.map(|result| result + 1)
947+
.and_then(|result| result.checked_add(1))
948948
}
949949

950950
/// Reflects an [`Interval`] around the point zero.
@@ -4157,7 +4157,22 @@ mod tests {
41574157
ScalarValue::TimestampNanosecond(Some(2_000_000_000), None),
41584158
)?;
41594159
assert_eq!(interval.cardinality().unwrap(), 1_000_000_001);
4160+
Ok(())
4161+
}
4162+
4163+
#[test]
4164+
fn test_cardinality_full_integer_range_does_not_overflow() -> Result<()> {
4165+
let interval = Interval::try_new(
4166+
ScalarValue::Int64(Some(i64::MIN)),
4167+
ScalarValue::Int64(Some(i64::MAX)),
4168+
)?;
4169+
assert_eq!(interval.cardinality(), None);
41604170

4171+
let interval = Interval::try_new(
4172+
ScalarValue::UInt64(Some(0)),
4173+
ScalarValue::UInt64(Some(u64::MAX)),
4174+
)?;
4175+
assert_eq!(interval.cardinality(), None);
41614176
Ok(())
41624177
}
41634178

datafusion/sqllogictest/test_files/select.slt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,12 @@ physical_plan
960960
01)ProjectionExec: expr=[c1@0 >= 2 AND c1@0 <= 3 as select_between_data.c1 BETWEEN Int64(2) AND Int64(3)]
961961
02)--DataSourceExec: partitions=1, partition_sizes=[1]
962962

963+
# regression test: full i64 BETWEEN bounds should not overflow
964+
query I
965+
SELECT * FROM (VALUES (1)) AS t(x)
966+
WHERE x BETWEEN -9223372036854775808 AND 9223372036854775807
967+
----
968+
1
963969

964970
# TODO: query_get_indexed_field
965971

0 commit comments

Comments
 (0)