mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-03 23:34:24 +01:00
Add Or bytecode
Take the logical OR of the values in register P1 and P2 and store the answer in register P3. If either P1 or P2 is nonzero (true) then the result is 1 (true) even if the other input is NULL. A NULL and false or two NULLs give a NULL output.
This commit is contained in:
@@ -493,7 +493,7 @@ Modifiers:
|
||||
| OpenWrite | No |
|
||||
| OpenWriteAsync | Yes |
|
||||
| OpenWriteAwait | Yes |
|
||||
| Or | No |
|
||||
| Or | Yes |
|
||||
| Pagecount | No |
|
||||
| Param | No |
|
||||
| ParseSchema | No |
|
||||
|
||||
@@ -612,6 +612,13 @@ pub fn translate_expr(
|
||||
dest: target_register,
|
||||
});
|
||||
}
|
||||
ast::Operator::Or => {
|
||||
program.emit_insn(Insn::Or {
|
||||
lhs: e1_reg,
|
||||
rhs: e2_reg,
|
||||
dest: target_register,
|
||||
});
|
||||
}
|
||||
ast::Operator::BitwiseAnd => {
|
||||
program.emit_insn(Insn::BitAnd {
|
||||
lhs: e1_reg,
|
||||
|
||||
@@ -1129,6 +1129,15 @@ pub fn insn_to_str(
|
||||
0,
|
||||
format!("r[{}]=(r[{}] && r[{}])", dest, lhs, rhs),
|
||||
),
|
||||
Insn::Or { lhs, rhs, dest } => (
|
||||
"Or",
|
||||
*rhs as i32,
|
||||
*lhs as i32,
|
||||
*dest as i32,
|
||||
OwnedValue::build_text(Rc::new("".to_string())),
|
||||
0,
|
||||
format!("r[{}]=(r[{}] || r[{}])", dest, lhs, rhs),
|
||||
),
|
||||
};
|
||||
format!(
|
||||
"{:<4} {:<17} {:<4} {:<4} {:<4} {:<13} {:<2} {}",
|
||||
|
||||
@@ -557,6 +557,12 @@ pub enum Insn {
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
/// Take the logical OR of the values in register P1 and P2 and store the answer in register P3.
|
||||
Or {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
}
|
||||
|
||||
fn cast_text_to_numerical(value: &str) -> OwnedValue {
|
||||
@@ -980,9 +986,43 @@ pub fn exec_and(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exec_or(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
if let OwnedValue::Agg(agg) = lhs {
|
||||
lhs = agg.final_value();
|
||||
}
|
||||
if let OwnedValue::Agg(agg) = rhs {
|
||||
rhs = agg.final_value();
|
||||
}
|
||||
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Null, OwnedValue::Null)
|
||||
| (OwnedValue::Null, OwnedValue::Float(0.0))
|
||||
| (OwnedValue::Float(0.0), OwnedValue::Null)
|
||||
| (OwnedValue::Null, OwnedValue::Integer(0))
|
||||
| (OwnedValue::Integer(0), OwnedValue::Null) => OwnedValue::Null,
|
||||
(OwnedValue::Float(0.0), OwnedValue::Integer(0))
|
||||
| (OwnedValue::Integer(0), OwnedValue::Float(0.0))
|
||||
| (OwnedValue::Float(0.0), OwnedValue::Float(0.0))
|
||||
| (OwnedValue::Integer(0), OwnedValue::Integer(0)) => OwnedValue::Integer(0),
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_or(
|
||||
&cast_text_to_numerical(&lhs.value),
|
||||
&cast_text_to_numerical(&rhs.value),
|
||||
),
|
||||
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
|
||||
exec_or(&cast_text_to_numerical(&text.value), other)
|
||||
}
|
||||
_ => OwnedValue::Integer(1),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::OwnedValue;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
types::{LimboText, OwnedValue},
|
||||
vdbe::insn::exec_or,
|
||||
};
|
||||
|
||||
use super::exec_and;
|
||||
|
||||
@@ -1012,4 +1052,54 @@ mod tests {
|
||||
assert_eq!(exec_and(lhs, rhs), outpus[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exec_or() {
|
||||
let inputs = vec![
|
||||
(OwnedValue::Integer(0), OwnedValue::Null),
|
||||
(OwnedValue::Null, OwnedValue::Integer(1)),
|
||||
(OwnedValue::Null, OwnedValue::Null),
|
||||
(OwnedValue::Float(0.0), OwnedValue::Null),
|
||||
(OwnedValue::Integer(1), OwnedValue::Float(2.2)),
|
||||
(OwnedValue::Float(0.0), OwnedValue::Integer(0)),
|
||||
(
|
||||
OwnedValue::Integer(0),
|
||||
OwnedValue::Text(LimboText::new(Rc::new("string".to_string()))),
|
||||
),
|
||||
(
|
||||
OwnedValue::Integer(0),
|
||||
OwnedValue::Text(LimboText::new(Rc::new("1".to_string()))),
|
||||
),
|
||||
(
|
||||
OwnedValue::Integer(0),
|
||||
OwnedValue::Text(LimboText::new(Rc::new("".to_string()))),
|
||||
),
|
||||
];
|
||||
let outpus = vec![
|
||||
OwnedValue::Null,
|
||||
OwnedValue::Integer(1),
|
||||
OwnedValue::Null,
|
||||
OwnedValue::Null,
|
||||
OwnedValue::Integer(1),
|
||||
OwnedValue::Integer(0),
|
||||
OwnedValue::Integer(0),
|
||||
OwnedValue::Integer(1),
|
||||
OwnedValue::Integer(0),
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
inputs.len(),
|
||||
outpus.len(),
|
||||
"Inputs and Outputs should have same size"
|
||||
);
|
||||
for (i, (lhs, rhs)) in inputs.iter().enumerate() {
|
||||
assert_eq!(
|
||||
exec_or(lhs, rhs),
|
||||
outpus[i],
|
||||
"Wrong OR for lhs: {}, rhs: {}",
|
||||
lhs,
|
||||
rhs
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ use crate::{resolve_ext_path, Connection, Result, Rows, TransactionState, DATABA
|
||||
use datetime::{exec_date, exec_datetime_full, exec_julianday, exec_time, exec_unixepoch};
|
||||
use insn::{
|
||||
exec_add, exec_and, exec_bit_and, exec_bit_not, exec_bit_or, exec_boolean_not, exec_concat,
|
||||
exec_divide, exec_multiply, exec_remainder, exec_shift_left, exec_shift_right, exec_subtract,
|
||||
exec_divide, exec_multiply, exec_or, exec_remainder, exec_shift_left, exec_shift_right,
|
||||
exec_subtract,
|
||||
};
|
||||
use likeop::{construct_like_escape_arg, exec_glob, exec_like_with_escape};
|
||||
use rand::distributions::{Distribution, Uniform};
|
||||
@@ -2351,6 +2352,11 @@ impl Program {
|
||||
exec_and(&state.registers[*lhs], &state.registers[*rhs]);
|
||||
state.pc += 1;
|
||||
}
|
||||
Insn::Or { lhs, rhs, dest } => {
|
||||
state.registers[*dest] =
|
||||
exec_or(&state.registers[*lhs], &state.registers[*rhs]);
|
||||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user