Fix incorrect CAST text->numeric if valid prefix is 1 char long

This commit is contained in:
Jussi Saurio
2025-02-18 15:07:36 +02:00
parent 899ba8367e
commit baf2aec3e9
2 changed files with 17 additions and 6 deletions

View File

@@ -3671,14 +3671,17 @@ fn affinity(datatype: &str) -> Affinity {
/// 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 {
let text = text.trim();
if text.is_empty() {
return OwnedValue::Integer(0);
}
if let Ok(i) = text.parse::<i64>() {
return OwnedValue::Integer(i);
}
// Try to find longest valid prefix that parses as an integer
// TODO: inefficient
let mut end_index = text.len() - 1;
while end_index > 0 {
if let Ok(i) = text[..=end_index].parse::<i64>() {
let mut end_index = text.len().saturating_sub(1) as isize;
while end_index >= 0 {
if let Ok(i) = text[..=end_index as usize].parse::<i64>() {
return OwnedValue::Integer(i);
}
end_index -= 1;
@@ -3692,14 +3695,17 @@ fn cast_text_to_integer(text: &str) -> OwnedValue {
/// If there is no prefix that can be interpreted as a real number, the result of the conversion is 0.0.
fn cast_text_to_real(text: &str) -> OwnedValue {
let trimmed = text.trim_start();
if trimmed.is_empty() {
return OwnedValue::Float(0.0);
}
if let Ok(num) = trimmed.parse::<f64>() {
return OwnedValue::Float(num);
}
// Try to find longest valid prefix that parses as a float
// TODO: inefficient
let mut end_index = trimmed.len() - 1;
while end_index > 0 {
if let Ok(num) = trimmed[..=end_index].parse::<f64>() {
let mut end_index = trimmed.len().saturating_sub(1) as isize;
while end_index >= 0 {
if let Ok(num) = trimmed[..=end_index as usize].parse::<f64>() {
return OwnedValue::Float(num);
}
end_index -= 1;

View File

@@ -739,6 +739,7 @@ do_execsql_test zeroblob-blob {
} {1}
# CAST tests - INTEGER affinity
do_execsql_test cast-text-to-integer {
SELECT CAST('123' AS INTEGER);
} {123}
@@ -747,6 +748,10 @@ do_execsql_test cast-text-with-spaces-to-integer {
SELECT CAST(' 123 ' AS INTEGER);
} {123}
do_execsql_test cast-text-with-trailing-junk-to-integer {
SELECT CAST('1abc' AS INTEGER);
} {1}
do_execsql_test cast-invalid-text-to-integer {
SELECT CAST('abc' AS INTEGER);
} {0}