Add substring scala function with 2 arg

This commit is contained in:
김선우
2024-08-15 18:47:32 +09:00
parent 3fa3c5c002
commit dc48c2e71d
4 changed files with 53 additions and 20 deletions

View File

@@ -107,7 +107,7 @@ This document describes the SQLite compatibility status of Limbo:
| substr(X,Y,Z) | No | |
| substr(X,Y) | No | |
| substring(X,Y,Z) | Yes | |
| substring(X,Y) | No | |
| substring(X,Y) | Yes | |
| total_changes() | No | |
| trim(X) | Yes | |
| trim(X,Y) | Yes | |

View File

@@ -304,9 +304,9 @@ pub fn translate_expr(
}
ScalarFunc::Substring => {
let args = if let Some(args) = args {
if args.len() != 3 {
if !(args.len() == 2 || args.len() == 3) {
crate::bail_parse_error!(
"{} function with not exactly 3 arguments",
"{} function with wrong number of arguments",
srf.to_string()
)
}
@@ -324,7 +324,9 @@ pub fn translate_expr(
translate_expr(program, select, &args[0], str_reg, cursor_hint)?;
translate_expr(program, select, &args[1], start_reg, cursor_hint)?;
translate_expr(program, select, &args[2], length_reg, cursor_hint)?;
if args.len() == 3 {
translate_expr(program, select, &args[2], length_reg, cursor_hint)?;
}
program.emit_insn(Insn::Function {
start_reg: str_reg,

View File

@@ -1650,20 +1650,31 @@ fn exec_minmax<'a>(
}
fn exec_substring(str_value: &OwnedValue, start_value: &OwnedValue, length_value: &OwnedValue) -> OwnedValue {
match (str_value, start_value, length_value) {
(OwnedValue::Text(str), OwnedValue::Integer(start), OwnedValue::Integer(length)) => {
let start = *start as usize;
if (start as usize) > str.len() {
OwnedValue::Text(Rc::new("".to_string()))
} else {
let length = *length as usize;
let start_idx = start - 1;
let end = start_idx + length;
let substring = &str[start_idx..end.min(str.len())];
OwnedValue::Text(Rc::new(substring.to_string()))
}
if let (OwnedValue::Text(str), OwnedValue::Integer(start), OwnedValue::Integer(length)) = (str_value, start_value, length_value) {
let start = *start as usize;
if start > str.len() {
return OwnedValue::Text(Rc::new("".to_string()));
}
_ => OwnedValue::Null,
let start_idx = start - 1;
let str_len = str.len();
let end = if *length != -1 { start_idx + *length as usize } else { str_len };
let substring = &str[start_idx..end.min(str_len)];
OwnedValue::Text(Rc::new(substring.to_string()))
} else if let (OwnedValue::Text(str), OwnedValue::Integer(start)) = (str_value, start_value) {
let start = *start as usize;
if start > str.len() {
return OwnedValue::Text(Rc::new("".to_string()));
}
let start_idx = start - 1;
let str_len = str.len();
let substring = &str[start_idx..str_len];
OwnedValue::Text(Rc::new(substring.to_string()))
} else {
OwnedValue::Null
}
}
@@ -2190,5 +2201,17 @@ mod tests {
let length_value = OwnedValue::Integer(3);
let expected_val = OwnedValue::Text(Rc::new(String::from("")));
assert_eq!(exec_substring(&str_value, &start_value, &length_value), expected_val);
let str_value = OwnedValue::Text(Rc::new("limbo".to_string()));
let start_value = OwnedValue::Integer(3);
let length_value = OwnedValue::Null;
let expected_val = OwnedValue::Text(Rc::new(String::from("mbo")));
assert_eq!(exec_substring(&str_value, &start_value, &length_value), expected_val);
let str_value = OwnedValue::Text(Rc::new("limbo".to_string()));
let start_value = OwnedValue::Integer(10);
let length_value = OwnedValue::Null;
let expected_val = OwnedValue::Text(Rc::new(String::from("")));
}
}

View File

@@ -239,18 +239,26 @@ do_execsql_test max-null {
select max(null,null)
} {}
do_execsql_test substr {
do_execsql_test substr-3-args {
SELECT substr('limbo', 1, 3);
} {lim}
do_execsql_test substr-exceed-length {
do_execsql_test substr-3-args-exceed-length {
SELECT substr('limbo', 1, 10);
} {limbo}
do_execsql_test substr-start-exceed-length {
do_execsql_test substr-3-args-start-exceed-length {
SELECT substr('limbo', 10, 3);
} {}
do_execsql_test substr-2-args {
SELECT substr('limbo', 3);
} {mbo}
do_execsql_test substr-2-args-exceed-length {
SELECT substr('limbo', 10);
} {}
do_execsql_test date-current-date {
SELECT length(date('now')) = 10;
} {1}