Merge 'substr scalar should also work with non-text values' from Diego Reis

Closes #3306
Not only blobs, but numbers are also cast to text

Closes #3439
This commit is contained in:
Jussi Saurio
2025-09-30 10:33:40 +03:00
committed by GitHub
3 changed files with 25 additions and 3 deletions

View File

@@ -387,6 +387,7 @@ impl Value {
};
}
/// Cast Value to String, if Value is NULL returns None
pub fn cast_text(&self) -> Option<String> {
Some(match self {
Value::Null => return None,

View File

@@ -8352,12 +8352,12 @@ impl Value {
}
pub fn exec_substring(
str_value: &Value,
value: &Value,
start_value: &Value,
length_value: Option<&Value>,
) -> Value {
if let (Value::Text(str), Value::Integer(start)) = (str_value, start_value) {
let str_len = str.as_str().len() as i64;
if let (Some(str), Value::Integer(start)) = (value.cast_text(), start_value) {
let str_len = str.len() as i64;
// The left-most character of X is number 1.
// If Y is negative then the first character of the substring is found by counting from the right rather than the left.

View File

@@ -622,6 +622,27 @@ do_execsql_test substring-2-args-exceed-length {
SELECT substring('limbo', 10);
} {}
do_execsql_test substring-with-blob {
select substr(x'446F6E7450616E696321', 0);
} {DontPanic!}
do_execsql_test substring-with-blob-size {
select substr(x'446F6E7450616E696321', 5, 6);
} {Panic!}
# https://github.com/tursodatabase/turso/issues/3306
do_execsql_test substring-with-blob-sanity {
with t as (select hex(substr(x'414243',2,1)) as slice) select slice, typeof(slice), length(slice) from t;
} {42|text|2}
do_execsql_test substring-with-numbers {
select substr(12345678987654, 5, 6);
} {567898}
do_execsql_test substring-with-numbers {
select substr(12345678987654, 0);
} {12345678987654}
do_execsql_test typeof-null {
SELECT typeof(null);
} {null}