Respect jump_if_true in like implementation

This commit is contained in:
Bennett Clement
2024-07-16 17:17:23 +08:00
parent 6f983702c3
commit 3c4f2b07e6
3 changed files with 32 additions and 24 deletions

View File

@@ -788,7 +788,7 @@ fn translate_condition_expr(
ast::LikeOperator::Match => todo!(),
ast::LikeOperator::Regexp => todo!(),
}
if *not {
if jump_if_true ^ *not {
program.emit_insn_with_label_dependency(
Insn::If {
reg: cur_reg,

View File

@@ -796,7 +796,7 @@ impl Program {
null_reg,
} => {
assert!(*target_pc >= 0);
if jump_if(&state.registers[*reg], &state.registers[*null_reg], false) {
if exec_if(&state.registers[*reg], &state.registers[*null_reg], false) {
state.pc = *target_pc;
} else {
state.pc += 1;
@@ -808,7 +808,7 @@ impl Program {
null_reg,
} => {
assert!(*target_pc >= 0);
if jump_if(&state.registers[*reg], &state.registers[*null_reg], true) {
if exec_if(&state.registers[*reg], &state.registers[*null_reg], true) {
state.pc = *target_pc;
} else {
state.pc += 1;
@@ -1242,7 +1242,7 @@ impl Program {
let text = state.registers[start_reg + 1].clone();
let result = match (pattern, text) {
(OwnedValue::Text(pattern), OwnedValue::Text(text)) => {
OwnedValue::Integer(like(&pattern, &text) as i64)
OwnedValue::Integer(exec_like(&pattern, &text) as i64)
}
_ => {
unreachable!("Like on non-text registers");
@@ -1765,13 +1765,13 @@ fn get_indent_count(indent_count: usize, curr_insn: &Insn, prev_insn: Option<&In
}
// Implements LIKE pattern matching.
fn like(pattern: &str, text: &str) -> bool {
fn exec_like(pattern: &str, text: &str) -> bool {
let re = Regex::new(&format!("{}", pattern.replace("%", ".*").replace("_", "."))).unwrap();
re.is_match(text)
}
// step_if returns whether you should jump
fn jump_if(reg: &OwnedValue, null_reg: &OwnedValue, not: bool) -> bool {
// exec_if returns whether you should jump
fn exec_if(reg: &OwnedValue, null_reg: &OwnedValue, not: bool) -> bool {
match reg {
OwnedValue::Integer(0) | OwnedValue::Float(0.0) => not,
OwnedValue::Integer(_) | OwnedValue::Float(_) => !not,
@@ -1789,38 +1789,38 @@ mod tests {
#[test]
fn test_like() {
assert!(like("a%", "aaaa"));
assert!(like("%a%a", "aaaa"));
assert!(like("%a.a", "aaaa"));
assert!(like("a.a%", "aaaa"));
assert!(!like("%a.ab", "aaaa"));
assert!(exec_like("a%", "aaaa"));
assert!(exec_like("%a%a", "aaaa"));
assert!(exec_like("%a.a", "aaaa"));
assert!(exec_like("a.a%", "aaaa"));
assert!(!exec_like("%a.ab", "aaaa"));
}
#[test]
fn test_jump_if() {
fn test_exec_if() {
let reg = OwnedValue::Integer(0);
let null_reg = OwnedValue::Integer(0);
assert_eq!(jump_if(&reg, &null_reg, false), false);
assert_eq!(jump_if(&reg, &null_reg, true), true);
assert_eq!(exec_if(&reg, &null_reg, false), false);
assert_eq!(exec_if(&reg, &null_reg, true), true);
let reg = OwnedValue::Integer(1);
let null_reg = OwnedValue::Integer(0);
assert_eq!(jump_if(&reg, &null_reg, false), true);
assert_eq!(jump_if(&reg, &null_reg, true), false);
assert_eq!(exec_if(&reg, &null_reg, false), true);
assert_eq!(exec_if(&reg, &null_reg, true), false);
let reg = OwnedValue::Null;
let null_reg = OwnedValue::Integer(0);
assert_eq!(jump_if(&reg, &null_reg, false), false);
assert_eq!(jump_if(&reg, &null_reg, true), false);
assert_eq!(exec_if(&reg, &null_reg, false), false);
assert_eq!(exec_if(&reg, &null_reg, true), false);
let reg = OwnedValue::Null;
let null_reg = OwnedValue::Integer(1);
assert_eq!(jump_if(&reg, &null_reg, false), true);
assert_eq!(jump_if(&reg, &null_reg, true), true);
assert_eq!(exec_if(&reg, &null_reg, false), true);
assert_eq!(exec_if(&reg, &null_reg, true), true);
let reg = OwnedValue::Null;
let null_reg = OwnedValue::Null;
assert_eq!(jump_if(&reg, &null_reg, false), false);
assert_eq!(jump_if(&reg, &null_reg, true), false);
assert_eq!(exec_if(&reg, &null_reg, false), false);
assert_eq!(exec_if(&reg, &null_reg, true), false);
}
}

View File

@@ -22,7 +22,7 @@ do_execsql_test where-like {
} {4|sweater|25.0
5|sweatshirt|74.0}
do_execsql_test where-not-like {
do_execsql_test where-not-like-and {
select * from products where name not like 'sweat%' and price >= 70.0;
} {1|hat|79.0
2|cap|82.0
@@ -30,3 +30,11 @@ do_execsql_test where-not-like {
7|jeans|78.0
8|sneakers|82.0
11|accessories|81.0}
do_execsql_test where-like-or {
select * from products where name like 'sweat%' or price >= 80.0;
} {2|cap|82.0
4|sweater|25.0
5|sweatshirt|74.0
8|sneakers|82.0
11|accessories|81.0}