Skip to content

Commit eb4be68

Browse files
authored
Return null for overflow when casting string to integer under safe option enabled (#5398)
* Return null for overflow when casting string to integer * Use atoi_simd * Use atoi * Return to str.parse. * Revert "Return to str.parse." This reverts commit 53dd047. * Check trailing string
1 parent a88d70d commit eb4be68

File tree

3 files changed

+26
-1
lines changed

3 files changed

+26
-1
lines changed

arrow-cast/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ chrono = { workspace = true }
4949
half = { version = "2.1", default-features = false }
5050
num = { version = "0.4", default-features = false, features = ["std"] }
5151
lexical-core = { version = "^0.8", default-features = false, features = ["write-integers", "write-floats", "parse-integers", "parse-floats"] }
52+
atoi = "2.0.0"
5253
comfy-table = { version = "7.0", optional = true, default-features = false }
5354
base64 = "0.21"
5455

arrow-cast/src/cast.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4911,6 +4911,25 @@ mod tests {
49114911
assert!(c.is_null(2));
49124912
}
49134913

4914+
#[test]
4915+
fn test_cast_string_to_integral_overflow() {
4916+
let str = Arc::new(StringArray::from(vec![
4917+
Some("123"),
4918+
Some("-123"),
4919+
Some("86374"),
4920+
None,
4921+
])) as ArrayRef;
4922+
4923+
let options = CastOptions {
4924+
safe: true,
4925+
format_options: FormatOptions::default(),
4926+
};
4927+
let res = cast_with_options(&str, &DataType::Int16, &options).expect("should cast to i16");
4928+
let expected =
4929+
Arc::new(Int16Array::from(vec![Some(123), Some(-123), None, None])) as ArrayRef;
4930+
assert_eq!(&res, &expected);
4931+
}
4932+
49144933
#[test]
49154934
fn test_cast_string_to_timestamp() {
49164935
let a1 = Arc::new(StringArray::from(vec![

arrow-cast/src/parse.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,12 @@ macro_rules! parser_primitive {
438438
($t:ty) => {
439439
impl Parser for $t {
440440
fn parse(string: &str) -> Option<Self::Native> {
441-
lexical_core::parse::<Self::Native>(string.as_bytes()).ok()
441+
match atoi::FromRadix10SignedChecked::from_radix_10_signed_checked(
442+
string.as_bytes(),
443+
) {
444+
(Some(n), x) if x == string.len() => Some(n),
445+
_ => None,
446+
}
442447
}
443448
}
444449
};

0 commit comments

Comments
 (0)