Merge pull request #246 from macroexpansion/feature/add-rtrim-scalar-function

This commit is contained in:
Pekka Enberg
2024-07-28 18:30:09 +03:00
committed by GitHub
5 changed files with 92 additions and 4 deletions

View File

@@ -95,8 +95,8 @@ This document describes the SQLite compatibility status of Limbo:
| replace(X,Y,Z) | No | |
| round(X) | Yes | |
| round(X,Y) | Yes | |
| rtrim(X) | No | |
| rtrim(X,Y) | No | |
| rtrim(X) | Yes | |
| rtrim(X,Y) | Yes | |
| sign(X) | No | |
| soundex(X) | No | |
| sqlite_compileoption_get(N) | No | |

View File

@@ -35,6 +35,7 @@ pub enum ScalarFunc {
Random,
Trim,
LTrim,
RTrim,
Round,
Length,
Min,
@@ -54,6 +55,7 @@ impl ToString for ScalarFunc {
ScalarFunc::Random => "random".to_string(),
ScalarFunc::Trim => "trim".to_string(),
ScalarFunc::LTrim => "ltrim".to_string(),
ScalarFunc::RTrim => "rtrim".to_string(),
ScalarFunc::Round => "round".to_string(),
ScalarFunc::Length => "length".to_string(),
ScalarFunc::Min => "min".to_string(),
@@ -91,6 +93,7 @@ impl Func {
"random" => Ok(Func::Scalar(ScalarFunc::Random)),
"trim" => Ok(Func::Scalar(ScalarFunc::Trim)),
"ltrim" => Ok(Func::Scalar(ScalarFunc::LTrim)),
"rtrim" => Ok(Func::Scalar(ScalarFunc::RTrim)),
"round" => Ok(Func::Scalar(ScalarFunc::Round)),
"length" => Ok(Func::Scalar(ScalarFunc::Length)),
"date" => Ok(Func::Scalar(ScalarFunc::Date)),

View File

@@ -275,7 +275,10 @@ pub fn translate_expr(
});
Ok(target_register)
}
ScalarFunc::Trim | ScalarFunc::LTrim | ScalarFunc::Round => {
ScalarFunc::Trim
| ScalarFunc::LTrim
| ScalarFunc::RTrim
| ScalarFunc::Round => {
let args = if let Some(args) = args {
if args.len() > 2 {
crate::bail_parse_error!(

View File

@@ -1125,6 +1125,16 @@ impl Program {
state.registers[*dest] = result;
state.pc += 1;
}
ScalarFunc::RTrim => {
let start_reg = *start_reg;
let reg_value = state.registers[start_reg].clone();
let pattern_value = state.registers.get(start_reg + 1).cloned();
let result = exec_rtrim(&reg_value, pattern_value);
state.registers[*dest] = result;
state.pc += 1;
}
ScalarFunc::Round => {
let start_reg = *start_reg;
let reg_value = state.registers[start_reg].clone();
@@ -1379,6 +1389,25 @@ fn exec_ltrim(reg: &OwnedValue, pattern: Option<OwnedValue>) -> OwnedValue {
}
}
// Implements RTRIM pattern matching.
fn exec_rtrim(reg: &OwnedValue, pattern: Option<OwnedValue>) -> OwnedValue {
match (reg, pattern) {
(reg, Some(pattern)) => match reg {
OwnedValue::Text(_) | OwnedValue::Integer(_) | OwnedValue::Float(_) => {
let pattern_chars: Vec<char> = pattern.to_string().chars().collect();
OwnedValue::Text(Rc::new(
reg.to_string()
.trim_end_matches(&pattern_chars[..])
.to_string(),
))
}
_ => reg.to_owned(),
},
(OwnedValue::Text(t), None) => OwnedValue::Text(Rc::new(t.trim_end().to_string())),
(reg, _) => reg.to_owned(),
}
}
// exec_if returns whether you should jump
fn exec_if(reg: &OwnedValue, null_reg: &OwnedValue, not: bool) -> bool {
match reg {
@@ -1397,7 +1426,7 @@ fn exec_if(reg: &OwnedValue, null_reg: &OwnedValue, not: bool) -> bool {
mod tests {
use super::{
exec_abs, exec_if, exec_length, exec_like, exec_lower, exec_ltrim, exec_minmax,
exec_random, exec_round, exec_trim, exec_unicode, exec_upper, OwnedValue,
exec_random, exec_round, exec_rtrim, exec_trim, exec_unicode, exec_upper, OwnedValue,
};
use std::rc::Rc;
@@ -1518,6 +1547,23 @@ mod tests {
assert_eq!(exec_ltrim(&input_str, Some(pattern_str)), expected_str);
}
#[test]
fn test_rtrim() {
let input_str = OwnedValue::Text(Rc::new(String::from(" Bob and Alice ")));
let expected_str = OwnedValue::Text(Rc::new(String::from(" Bob and Alice")));
assert_eq!(exec_rtrim(&input_str, None), expected_str);
let input_str = OwnedValue::Text(Rc::new(String::from(" Bob and Alice ")));
let pattern_str = OwnedValue::Text(Rc::new(String::from("Bob and")));
let expected_str = OwnedValue::Text(Rc::new(String::from(" Bob and Alice")));
assert_eq!(exec_rtrim(&input_str, Some(pattern_str)), expected_str);
let input_str = OwnedValue::Text(Rc::new(String::from(" Bob and Alice ")));
let pattern_str = OwnedValue::Text(Rc::new(String::from("and Alice")));
let expected_str = OwnedValue::Text(Rc::new(String::from(" Bob")));
assert_eq!(exec_rtrim(&input_str, Some(pattern_str)), expected_str);
}
#[test]
fn test_upper_case() {
let input_str = OwnedValue::Text(Rc::new(String::from("Limbo")));

View File

@@ -123,6 +123,42 @@ do_execsql_test ltrim-no-match-pattern {
SELECT ltrim('Limbo', 'xyz');
} {Limbo}
do_execsql_test rtrim {
SELECT rtrim(' Limbo ');
} {" Limbo"}
do_execsql_test rtrim-number {
SELECT rtrim(1);
} {1}
do_execsql_test rtrim-null {
SELECT rtrim(null);
} {}
do_execsql_test rtrim-trailing-whitespace {
SELECT rtrim('Trailing ');
} {Trailing}
do_execsql_test rtrim-no-trailing-whitespace {
SELECT rtrim('Limbo');
} {Limbo}
do_execsql_test rtrim-pattern {
SELECT rtrim('Limbo', 'Limbo');
} {}
do_execsql_test rtrim-pattern-number {
SELECT rtrim(1, '1');
} {}
do_execsql_test rtrim-pattern-null {
SELECT rtrim(null, 'null');
} {}
do_execsql_test rtrim-no-match-pattern {
SELECT rtrim('Limbo', 'xyz');
} {Limbo}
do_execsql_test round-float-no-precision {
SELECT round(123.456);
} {123.0}