Add affinity based type coercion to comparison ops

This commit is contained in:
krishvishal 2025-06-06 16:12:32 +05:30 committed by Krishna Vishal
parent 7bd1589615
commit faa9aedbae

View file

@ -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::*;