Add affinity conversion to op_gt, op_le, op_lt, op_eq, op_ne

This commit is contained in:
krishvishal
2025-06-06 13:14:07 +05:30
committed by Krishna Vishal
parent 30ccbe46c7
commit e68293a1d1

View File

@@ -552,37 +552,64 @@ pub fn op_eq(
let lhs = *lhs;
let rhs = *rhs;
let target_pc = *target_pc;
let cond = *state.registers[lhs].get_owned_value() == *state.registers[rhs].get_owned_value();
let nulleq = flags.has_nulleq();
let jump_if_null = flags.has_jump_if_null();
let collation = collation.unwrap_or_default();
match (
state.registers[lhs].get_owned_value(),
state.registers[rhs].get_owned_value(),
) {
(_, Value::Null) | (Value::Null, _) => {
if (nulleq && cond) || (!nulleq && jump_if_null) {
let lhs_value = state.registers[lhs].get_owned_value();
let rhs_value = state.registers[rhs].get_owned_value();
// Fast path for integers
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
if lhs_value == rhs_value {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(Value::Text(lhs), Value::Text(rhs)) => {
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
if order.is_eq() {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(lhs, rhs) => {
if *lhs == *rhs {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
return Ok(InsnFunctionStepResult::Step);
}
// Handle NULL values
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
let cond = lhs_value == rhs_value; // Both NULL
if (nulleq && cond) || (!nulleq && jump_if_null) {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
return Ok(InsnFunctionStepResult::Step);
}
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 should_jump = match (
lhs_temp_reg.get_owned_value(),
rhs_temp_reg.get_owned_value(),
) {
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
order.is_eq()
}
(lhs, rhs) => *lhs == *rhs,
};
if lhs_converted {
state.registers[lhs] = lhs_temp_reg;
}
if rhs_converted {
state.registers[rhs] = rhs_temp_reg;
}
if should_jump {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
Ok(InsnFunctionStepResult::Step)
}
@@ -607,37 +634,64 @@ pub fn op_ne(
let lhs = *lhs;
let rhs = *rhs;
let target_pc = *target_pc;
let cond = *state.registers[lhs].get_owned_value() != *state.registers[rhs].get_owned_value();
let nulleq = flags.has_nulleq();
let jump_if_null = flags.has_jump_if_null();
let collation = collation.unwrap_or_default();
match (
state.registers[lhs].get_owned_value(),
state.registers[rhs].get_owned_value(),
) {
(_, Value::Null) | (Value::Null, _) => {
if (nulleq && cond) || (!nulleq && jump_if_null) {
let lhs_value = state.registers[lhs].get_owned_value();
let rhs_value = state.registers[rhs].get_owned_value();
// Fast path for integers
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
if lhs_value != rhs_value {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(Value::Text(lhs), Value::Text(rhs)) => {
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
if order.is_ne() {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(lhs, rhs) => {
if *lhs != *rhs {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
return Ok(InsnFunctionStepResult::Step);
}
// Handle NULL values
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
let cond = lhs_value != rhs_value; // At least one NULL
if (nulleq && cond) || (!nulleq && jump_if_null) {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
return Ok(InsnFunctionStepResult::Step);
}
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 should_jump = match (
lhs_temp_reg.get_owned_value(),
rhs_temp_reg.get_owned_value(),
) {
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
order.is_ne()
}
(lhs, rhs) => *lhs != *rhs,
};
if lhs_converted {
state.registers[lhs] = lhs_temp_reg;
}
if rhs_converted {
state.registers[rhs] = rhs_temp_reg;
}
if should_jump {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
Ok(InsnFunctionStepResult::Step)
}
@@ -664,33 +718,60 @@ pub fn op_lt(
let target_pc = *target_pc;
let jump_if_null = flags.has_jump_if_null();
let collation = collation.unwrap_or_default();
match (
state.registers[lhs].get_owned_value(),
state.registers[rhs].get_owned_value(),
) {
(_, Value::Null) | (Value::Null, _) => {
if jump_if_null {
let lhs_value = state.registers[lhs].get_owned_value();
let rhs_value = state.registers[rhs].get_owned_value();
// Fast path for integers
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
if lhs_value < rhs_value {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(Value::Text(lhs), Value::Text(rhs)) => {
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
if order.is_lt() {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(lhs, rhs) => {
if *lhs < *rhs {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
return Ok(InsnFunctionStepResult::Step);
}
// Handle NULL values
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
if jump_if_null {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
return Ok(InsnFunctionStepResult::Step);
}
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 should_jump = match (
lhs_temp_reg.get_owned_value(),
rhs_temp_reg.get_owned_value(),
) {
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
order.is_lt()
}
(lhs, rhs) => *lhs < *rhs,
};
if lhs_converted {
state.registers[lhs] = lhs_temp_reg;
}
if rhs_converted {
state.registers[rhs] = rhs_temp_reg;
}
if should_jump {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
Ok(InsnFunctionStepResult::Step)
}
@@ -717,33 +798,60 @@ pub fn op_le(
let target_pc = *target_pc;
let jump_if_null = flags.has_jump_if_null();
let collation = collation.unwrap_or_default();
match (
state.registers[lhs].get_owned_value(),
state.registers[rhs].get_owned_value(),
) {
(_, Value::Null) | (Value::Null, _) => {
if jump_if_null {
let lhs_value = state.registers[lhs].get_owned_value();
let rhs_value = state.registers[rhs].get_owned_value();
// Fast path for integers
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
if lhs_value <= rhs_value {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(Value::Text(lhs), Value::Text(rhs)) => {
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
if order.is_le() {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(lhs, rhs) => {
if *lhs <= *rhs {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
return Ok(InsnFunctionStepResult::Step);
}
// Handle NULL values
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
if jump_if_null {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
return Ok(InsnFunctionStepResult::Step);
}
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 should_jump = match (
lhs_temp_reg.get_owned_value(),
rhs_temp_reg.get_owned_value(),
) {
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
order.is_le()
}
(lhs, rhs) => *lhs <= *rhs,
};
if lhs_converted {
state.registers[lhs] = lhs_temp_reg;
}
if rhs_converted {
state.registers[rhs] = rhs_temp_reg;
}
if should_jump {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
Ok(InsnFunctionStepResult::Step)
}
@@ -770,33 +878,59 @@ pub fn op_gt(
let target_pc = *target_pc;
let jump_if_null = flags.has_jump_if_null();
let collation = collation.unwrap_or_default();
match (
state.registers[lhs].get_owned_value(),
state.registers[rhs].get_owned_value(),
) {
(_, Value::Null) | (Value::Null, _) => {
if jump_if_null {
let lhs_value = state.registers[lhs].get_owned_value();
let rhs_value = state.registers[rhs].get_owned_value();
// Fast path for integers
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
if lhs_value > rhs_value {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(Value::Text(lhs), Value::Text(rhs)) => {
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
if order.is_gt() {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(lhs, rhs) => {
if *lhs > *rhs {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
return Ok(InsnFunctionStepResult::Step);
}
// Handle NULL values
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
if jump_if_null {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
return Ok(InsnFunctionStepResult::Step);
}
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 should_jump = match (
lhs_temp_reg.get_owned_value(),
rhs_temp_reg.get_owned_value(),
) {
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
order.is_gt()
}
(lhs, rhs) => *lhs > *rhs,
};
if lhs_converted {
state.registers[lhs] = lhs_temp_reg;
}
if rhs_converted {
state.registers[rhs] = rhs_temp_reg;
}
if should_jump {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
Ok(InsnFunctionStepResult::Step)
}
@@ -815,41 +949,86 @@ pub fn op_ge(
collation,
} = insn
else {
unreachable!("unexpected Insn {:?}", insn)
unreachable!("unexpected Insn: {:?}", insn)
};
assert!(target_pc.is_offset());
let lhs = *lhs;
let rhs = *rhs;
let target_pc = *target_pc;
let jump_if_null = flags.has_jump_if_null();
let collation = collation.unwrap_or_default();
match (
state.registers[lhs].get_owned_value(),
state.registers[rhs].get_owned_value(),
let lhs_value = state.registers[lhs].get_owned_value();
let rhs_value = state.registers[rhs].get_owned_value();
println!("lhs_value: {:?}, rhs_value: {:?}", lhs_value, rhs_value);
println!("jump_if_null: {}", jump_if_null);
if matches!(lhs_value, Value::Integer(_)) && matches!(rhs_value, Value::Integer(_)) {
if lhs_value >= rhs_value {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
return Ok(InsnFunctionStepResult::Step);
}
if matches!(lhs_value, Value::Null) || matches!(rhs_value, Value::Null) {
if jump_if_null {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
return Ok(InsnFunctionStepResult::Step);
}
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);
println!(
"lhs_converted: {}, rhs_converted: {}",
lhs_converted, rhs_converted
);
println!(
"converted_lhs: {:?}, converted_rhs: {:?}",
lhs_temp_reg.get_owned_value(),
rhs_temp_reg.get_owned_value()
);
let should_jump = match (
lhs_temp_reg.get_owned_value(),
rhs_temp_reg.get_owned_value(),
) {
(_, Value::Null) | (Value::Null, _) => {
if jump_if_null {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
}
(Value::Text(lhs), Value::Text(rhs)) => {
let order = collation.compare_strings(lhs.as_str(), rhs.as_str());
if order.is_ge() {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
(Value::Text(lhs_text), Value::Text(rhs_text)) => {
let order = collation.compare_strings(lhs_text.as_str(), rhs_text.as_str());
order.is_ge()
}
(lhs, rhs) => {
if *lhs >= *rhs {
state.pc = target_pc.to_offset_int();
true
} else {
state.pc += 1;
false
}
}
};
if lhs_converted {
state.registers[lhs] = lhs_temp_reg;
}
if rhs_converted {
state.registers[rhs] = rhs_temp_reg;
}
if should_jump {
state.pc = target_pc.to_offset_int();
} else {
state.pc += 1;
}
Ok(InsnFunctionStepResult::Step)
}