mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 18:18:03 +00:00
Add affinity based type coercion to comparison ops
This commit is contained in:
parent
7bd1589615
commit
faa9aedbae
1 changed files with 358 additions and 12 deletions
|
@ -554,6 +554,8 @@ pub fn op_eq(
|
|||
let target_pc = *target_pc;
|
||||
let nulleq = flags.has_nulleq();
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let affinity = flags.get_affinity();
|
||||
println!("execute affinity: {:?}", affinity);
|
||||
let collation = collation.unwrap_or_default();
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
|
@ -583,8 +585,61 @@ pub fn op_eq(
|
|||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
let mut lhs_converted = false;
|
||||
let mut rhs_converted = false;
|
||||
|
||||
match affinity {
|
||||
Affinity::Numeric | Affinity::Integer => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if lhs_is_text {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
if rhs_is_text {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Text => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if is_numeric_value(&lhs_temp_reg) {
|
||||
lhs_converted = stringify_register(&mut lhs_temp_reg);
|
||||
}
|
||||
|
||||
if is_numeric_value(&rhs_temp_reg) {
|
||||
rhs_converted = stringify_register(&mut rhs_temp_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Real => {
|
||||
if matches!(lhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
|
||||
if matches!(rhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = lhs_temp_reg.get_owned_value() {
|
||||
lhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
lhs_converted = true;
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = rhs_temp_reg.get_owned_value() {
|
||||
rhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
rhs_converted = true;
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Blob => {} // Do nothing for blob affinity.
|
||||
}
|
||||
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
|
@ -636,6 +691,8 @@ pub fn op_ne(
|
|||
let target_pc = *target_pc;
|
||||
let nulleq = flags.has_nulleq();
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let affinity = flags.get_affinity();
|
||||
println!("execute affinity: {:?}", affinity);
|
||||
let collation = collation.unwrap_or_default();
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
|
@ -665,8 +722,61 @@ pub fn op_ne(
|
|||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
let mut lhs_converted = false;
|
||||
let mut rhs_converted = false;
|
||||
|
||||
match affinity {
|
||||
Affinity::Numeric | Affinity::Integer => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if lhs_is_text {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
if rhs_is_text {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Text => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if is_numeric_value(&lhs_temp_reg) {
|
||||
lhs_converted = stringify_register(&mut lhs_temp_reg);
|
||||
}
|
||||
|
||||
if is_numeric_value(&rhs_temp_reg) {
|
||||
rhs_converted = stringify_register(&mut rhs_temp_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Real => {
|
||||
if matches!(lhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
|
||||
if matches!(rhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = lhs_temp_reg.get_owned_value() {
|
||||
lhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
lhs_converted = true;
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = rhs_temp_reg.get_owned_value() {
|
||||
rhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
rhs_converted = true;
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Blob => {} // Do nothing for blob affinity.
|
||||
}
|
||||
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
|
@ -717,6 +827,8 @@ pub fn op_lt(
|
|||
let rhs = *rhs;
|
||||
let target_pc = *target_pc;
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let affinity = flags.get_affinity();
|
||||
println!("execute affinity: {:?}", affinity);
|
||||
let collation = collation.unwrap_or_default();
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
|
@ -745,8 +857,61 @@ pub fn op_lt(
|
|||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
let mut lhs_converted = false;
|
||||
let mut rhs_converted = false;
|
||||
|
||||
match affinity {
|
||||
Affinity::Numeric | Affinity::Integer => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if lhs_is_text {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
if rhs_is_text {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Text => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if is_numeric_value(&lhs_temp_reg) {
|
||||
lhs_converted = stringify_register(&mut lhs_temp_reg);
|
||||
}
|
||||
|
||||
if is_numeric_value(&rhs_temp_reg) {
|
||||
rhs_converted = stringify_register(&mut rhs_temp_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Real => {
|
||||
if matches!(lhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
|
||||
if matches!(rhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = lhs_temp_reg.get_owned_value() {
|
||||
lhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
lhs_converted = true;
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = rhs_temp_reg.get_owned_value() {
|
||||
rhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
rhs_converted = true;
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Blob => {} // Do nothing for blob affinity.
|
||||
}
|
||||
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
|
@ -797,6 +962,8 @@ pub fn op_le(
|
|||
let rhs = *rhs;
|
||||
let target_pc = *target_pc;
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let affinity = flags.get_affinity();
|
||||
println!("execute affinity: {:?}", affinity);
|
||||
let collation = collation.unwrap_or_default();
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
|
@ -825,8 +992,61 @@ pub fn op_le(
|
|||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
let mut lhs_converted = false;
|
||||
let mut rhs_converted = false;
|
||||
|
||||
match affinity {
|
||||
Affinity::Numeric | Affinity::Integer => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if lhs_is_text {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
if rhs_is_text {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Text => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if is_numeric_value(&lhs_temp_reg) {
|
||||
lhs_converted = stringify_register(&mut lhs_temp_reg);
|
||||
}
|
||||
|
||||
if is_numeric_value(&rhs_temp_reg) {
|
||||
rhs_converted = stringify_register(&mut rhs_temp_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Real => {
|
||||
if matches!(lhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
|
||||
if matches!(rhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = lhs_temp_reg.get_owned_value() {
|
||||
lhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
lhs_converted = true;
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = rhs_temp_reg.get_owned_value() {
|
||||
rhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
rhs_converted = true;
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Blob => {} // Do nothing for blob affinity.
|
||||
}
|
||||
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
|
@ -877,6 +1097,8 @@ pub fn op_gt(
|
|||
let rhs = *rhs;
|
||||
let target_pc = *target_pc;
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let affinity = flags.get_affinity();
|
||||
println!("execute affinity: {:?}", affinity);
|
||||
let collation = collation.unwrap_or_default();
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
|
@ -905,8 +1127,60 @@ pub fn op_gt(
|
|||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
let mut lhs_converted = false;
|
||||
let mut rhs_converted = false;
|
||||
|
||||
match affinity {
|
||||
Affinity::Numeric | Affinity::Integer => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if lhs_is_text {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
if rhs_is_text {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Text => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if is_numeric_value(&lhs_temp_reg) {
|
||||
lhs_converted = stringify_register(&mut lhs_temp_reg);
|
||||
}
|
||||
|
||||
if is_numeric_value(&rhs_temp_reg) {
|
||||
rhs_converted = stringify_register(&mut rhs_temp_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Real => {
|
||||
if matches!(lhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
if matches!(rhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = lhs_temp_reg.get_owned_value() {
|
||||
lhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
lhs_converted = true;
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = rhs_temp_reg.get_owned_value() {
|
||||
rhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
rhs_converted = true;
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Blob => {} // Do nothing for blob affinity.
|
||||
}
|
||||
|
||||
let should_jump = match (
|
||||
lhs_temp_reg.get_owned_value(),
|
||||
|
@ -958,6 +1232,8 @@ pub fn op_ge(
|
|||
let rhs = *rhs;
|
||||
let target_pc = *target_pc;
|
||||
let jump_if_null = flags.has_jump_if_null();
|
||||
let affinity = flags.get_affinity();
|
||||
println!("execute affinity: {:?}", affinity);
|
||||
let collation = collation.unwrap_or_default();
|
||||
|
||||
let lhs_value = state.registers[lhs].get_owned_value();
|
||||
|
@ -987,8 +1263,60 @@ pub fn op_ge(
|
|||
let mut lhs_temp_reg = state.registers[lhs].clone();
|
||||
let mut rhs_temp_reg = state.registers[rhs].clone();
|
||||
|
||||
let lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
let rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
let mut lhs_converted = false;
|
||||
let mut rhs_converted = false;
|
||||
|
||||
match affinity {
|
||||
Affinity::Numeric | Affinity::Integer => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if lhs_is_text {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
if rhs_is_text {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Text => {
|
||||
let lhs_is_text = matches!(lhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
let rhs_is_text = matches!(rhs_temp_reg.get_owned_value(), Value::Text(_));
|
||||
|
||||
if lhs_is_text || rhs_is_text {
|
||||
if is_numeric_value(&lhs_temp_reg) {
|
||||
lhs_converted = stringify_register(&mut lhs_temp_reg);
|
||||
}
|
||||
|
||||
if is_numeric_value(&rhs_temp_reg) {
|
||||
rhs_converted = stringify_register(&mut rhs_temp_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Real => {
|
||||
if matches!(lhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
lhs_converted = apply_numeric_affinity(&mut lhs_temp_reg, false);
|
||||
}
|
||||
if matches!(rhs_temp_reg.get_owned_value(), Value::Text(_)) {
|
||||
rhs_converted = apply_numeric_affinity(&mut rhs_temp_reg, false);
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = lhs_temp_reg.get_owned_value() {
|
||||
lhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
lhs_converted = true;
|
||||
}
|
||||
|
||||
if let Value::Integer(i) = rhs_temp_reg.get_owned_value() {
|
||||
rhs_temp_reg = Register::Value(Value::Float(*i as f64));
|
||||
rhs_converted = true;
|
||||
}
|
||||
}
|
||||
|
||||
Affinity::Blob => {} // Do nothing for blob affinity.
|
||||
}
|
||||
println!(
|
||||
"lhs_converted: {}, rhs_converted: {}",
|
||||
lhs_converted, rhs_converted
|
||||
|
@ -6699,6 +7027,24 @@ pub fn apply_numeric_affinity(register: &mut Register, try_for_int: bool) -> boo
|
|||
}
|
||||
}
|
||||
|
||||
fn is_numeric_value(reg: &Register) -> bool {
|
||||
matches!(reg.get_owned_value(), Value::Integer(_) | Value::Float(_))
|
||||
}
|
||||
|
||||
fn stringify_register(reg: &mut Register) -> bool {
|
||||
match reg.get_owned_value() {
|
||||
Value::Integer(i) => {
|
||||
*reg = Register::Value(Value::build_text(&i.to_string()));
|
||||
true
|
||||
}
|
||||
Value::Float(f) => {
|
||||
*reg = Register::Value(Value::build_text(&f.to_string()));
|
||||
true
|
||||
}
|
||||
Value::Text(_) | Value::Null | Value::Blob(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue