Fix (fuzzing tests) casting text to integer to match sqlite behavior

This commit is contained in:
PThorpe92
2025-02-22 20:47:57 -05:00
parent eb6019b453
commit 8f27a5fc92
2 changed files with 47 additions and 2 deletions

View File

@@ -688,6 +688,35 @@ pub enum Cookie {
UserVersion = 6,
}
fn cast_text_to_numerical(value: &str) -> OwnedValue {
if let Ok(x) = value.parse::<i64>() {
OwnedValue::Integer(x)
} else if let Ok(x) = value.parse::<f64>() {
OwnedValue::Float(x)
} else {
OwnedValue::Integer(0)
}
}
fn cast_text_to_numerical(value: &str) -> OwnedValue {
if let Ok(x) = value.parse::<i64>() {
OwnedValue::Integer(x)
} else if let Ok(x) = value.parse::<f64>() {
OwnedValue::Float(x)
} else {
let idx = value
.chars()
.enumerate()
.find_map(|(i, c)| match i {
i if i == 0 && c == '-' => None,
i if i > 0 && !c.is_ascii_digit() => Some(i),
_ => None,
})
.unwrap_or(0);
OwnedValue::Integer(value[0..idx].parse::<i64>().unwrap_or(0))
}
}
pub fn exec_add(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = lhs {
lhs = agg.final_value();

View File

@@ -3648,8 +3648,24 @@ fn exec_replace(source: &OwnedValue, pattern: &OwnedValue, replacement: &OwnedVa
/// When casting to INTEGER, if the text looks like a floating point value with an exponent, the exponent will be ignored
/// because it is no part of the integer prefix. For example, "CAST('123e+5' AS INTEGER)" results in 123, not in 12300000.
/// The CAST operator understands decimal integers only — conversion of hexadecimal integers stops at the "x" in the "0x" prefix of the hexadecimal integer string and thus result of the CAST is always zero.
fn cast_text_to_integer(text: &str) -> (OwnedValue, CastTextToIntResultCode) {
text_to_integer(text)
fn cast_text_to_integer(text: &str) -> OwnedValue {
let text = text.trim();
if text.is_empty() {
return OwnedValue::Integer(0);
}
if let Ok(i) = text.parse::<i64>() {
return OwnedValue::Integer(i);
}
let idx = text
.chars()
.enumerate()
.find_map(|(i, c)| match i {
i if i == 0 && c == '-' => None,
i if i > 0 && !c.is_ascii_digit() => Some(i),
_ => None,
})
.unwrap_or(0);
OwnedValue::Integer(text[0..idx].parse::<i64>().unwrap_or(0))
}
/// When casting a TEXT value to REAL, the longest possible prefix of the value that can be interpreted