Fix arithmetic operations for text values

This commit is contained in:
psvri 2025-01-04 00:34:04 +05:30
parent 90d01f468f
commit 2b879a4f40
2 changed files with 146 additions and 0 deletions

View file

@ -489,6 +489,16 @@ pub enum Insn {
},
}
fn cast_text_to_numerical(value: &str) -> OwnedValue {
if let Ok(x) = value.parse::<i64>() {
OwnedValue::Integer(x)
} else if let Ok(x) = value.parse::<f64>() {
OwnedValue::Float(x)
} else {
OwnedValue::Integer(0)
}
}
pub fn exec_add(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = lhs {
lhs = agg.final_value();
@ -502,6 +512,13 @@ pub fn exec_add(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
(OwnedValue::Float(f), OwnedValue::Integer(i))
| (OwnedValue::Integer(i), OwnedValue::Float(f)) => OwnedValue::Float(*f + *i as f64),
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_add(
&cast_text_to_numerical(&lhs.value),
&cast_text_to_numerical(&rhs.value),
),
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
exec_add(&cast_text_to_numerical(&text.value), other)
}
_ => todo!(),
}
}
@ -519,6 +536,16 @@ pub fn exec_subtract(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Float(lhs - *rhs as f64),
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(*lhs as f64 - rhs),
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_subtract(
&cast_text_to_numerical(&lhs.value),
&cast_text_to_numerical(&rhs.value),
),
(OwnedValue::Text(text), other) => {
exec_subtract(&cast_text_to_numerical(&text.value), other)
}
(other, OwnedValue::Text(text)) => {
exec_subtract(other, &cast_text_to_numerical(&text.value))
}
_ => todo!(),
}
}
@ -535,6 +562,14 @@ pub fn exec_multiply(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
(OwnedValue::Integer(i), OwnedValue::Float(f))
| (OwnedValue::Float(f), OwnedValue::Integer(i)) => OwnedValue::Float(*i as f64 * { *f }),
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_multiply(
&cast_text_to_numerical(&lhs.value),
&cast_text_to_numerical(&rhs.value),
),
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
exec_multiply(&cast_text_to_numerical(&text.value), other)
}
_ => todo!(),
}
}
@ -553,6 +588,12 @@ pub fn exec_divide(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Float(lhs / *rhs as f64),
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(*lhs as f64 / rhs),
(OwnedValue::Null, _) | (_, OwnedValue::Null) => OwnedValue::Null,
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_divide(
&cast_text_to_numerical(&lhs.value),
&cast_text_to_numerical(&rhs.value),
),
(OwnedValue::Text(text), other) => exec_divide(&cast_text_to_numerical(&text.value), other),
(other, OwnedValue::Text(text)) => exec_divide(other, &cast_text_to_numerical(&text.value)),
_ => todo!(),
}
}
@ -576,9 +617,17 @@ pub fn exec_bit_and(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
}
(OwnedValue::Float(lh), OwnedValue::Integer(rh)) => OwnedValue::Integer(*lh as i64 & rh),
(OwnedValue::Integer(lh), OwnedValue::Float(rh)) => OwnedValue::Integer(lh & *rh as i64),
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_bit_and(
&cast_text_to_numerical(&lhs.value),
&cast_text_to_numerical(&rhs.value),
),
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
exec_bit_and(&cast_text_to_numerical(&text.value), other)
}
_ => todo!(),
}
}
pub fn exec_bit_or(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
if let OwnedValue::Agg(agg) = lhs {
lhs = agg.final_value();
@ -594,6 +643,13 @@ pub fn exec_bit_or(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
(OwnedValue::Float(lh), OwnedValue::Float(rh)) => {
OwnedValue::Integer(*lh as i64 | *rh as i64)
}
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_bit_or(
&cast_text_to_numerical(&lhs.value),
&cast_text_to_numerical(&rhs.value),
),
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
exec_bit_or(&cast_text_to_numerical(&text.value), other)
}
_ => todo!(),
}
}
@ -632,6 +688,7 @@ pub fn exec_bit_not(mut reg: &OwnedValue) -> OwnedValue {
OwnedValue::Null => OwnedValue::Null,
OwnedValue::Integer(i) => OwnedValue::Integer(!i),
OwnedValue::Float(f) => OwnedValue::Integer(!(*f as i64)),
OwnedValue::Text(text) => exec_bit_not(&cast_text_to_numerical(&text.value)),
_ => todo!(),
}
}

View file

@ -31,6 +31,19 @@ do_execsql_test add-agg-float-agg-int {
SELECT sum(1.5) + sum(2)
} {3.5}
foreach {testnum lhs rhs ans} {
1 'a' 'a' 0
2 'a' 10 10
3 10 'a' 10
4 'a' 11.0 11.0
5 11.0 'a' 11.0
7 '1' '2' 3
8 '1.0' '2' 3.0
9 '1.0' '3.0' 4.0
} {
do_execsql_test add-text-$testnum "SELECT $lhs + $rhs" $::ans
}
do_execsql_test subtract-int {
SELECT 10 - 1
} {9}
@ -55,6 +68,19 @@ do_execsql_test subtract-agg-float-agg-int {
SELECT sum(3.5) - sum(1)
} {2.5}
foreach {testnum lhs rhs ans} {
1 'a' 'a' 0
2 'a' 10 -10
3 10 'a' 10
4 'a' 11.0 -11.0
5 11.0 'a' 11.0
7 '1' '2' -1
8 '1.0' '2' -1.0
9 '1.0' '3.0' -2.0
} {
do_execsql_test subtract-text-$testnum "SELECT $lhs - $rhs" $::ans
}
do_execsql_test multiply-int {
SELECT 10 * 2
} {20}
@ -83,6 +109,19 @@ do_execsql_test multiply-agg-float-agg-int {
SELECT sum(2.5) * sum(3)
} {7.5}
foreach {testnum lhs rhs ans} {
1 'a' 'a' 0
2 'a' 10 0
3 10 'a' 0
4 'a' 11.0 0.0
5 11.0 'a' 0.0
7 '1' '2' 2
8 '1.0' '2' 2.0
9 '1.0' '3.0' 3.0
} {
do_execsql_test multiply-text-$testnum "SELECT $lhs * $rhs" $::ans
}
do_execsql_test divide-int {
SELECT 10 / 2
} {5}
@ -131,6 +170,18 @@ do_execsql_test divide-agg-float-agg-int {
SELECT sum(4.0) / sum(2)
} {2.0}
foreach {testnum lhs rhs ans} {
1 'a' 'a' {}
2 'a' 10 0
3 10 'a' {}
4 'a' 11.0 0.0
5 11.0 'a' {}
7 '1' '2' 0
8 '1.0' '2' 0.5
9 '1.0' '4.0' 0.25
} {
do_execsql_test divide-text-$testnum "SELECT $lhs / $rhs" $::ans
}
do_execsql_test add-agg-int {
SELECT sum(id) + 10 from products
@ -299,6 +350,21 @@ do_execsql_test bitwise-and-int-agg-int-agg {
SELECT sum(id) & sum(id) from products
} {66}
foreach {testnum lhs rhs ans} {
1 'a' 'a' 0
2 'a' 10 0
3 10 'a' 0
4 'a' 11.0 0
5 11.0 'a' 0
7 '1' '2' 0
8 '1.0' '2' 0
9 '1.0' '4.0' 0
10 '1.0' '1.0' 1
11 '1' '1' 1
} {
do_execsql_test bitwise-and-text-$testnum "SELECT $lhs & $rhs" $::ans
}
do_execsql_test bitwise-or-int-null {
SELECT 1234 | NULL
@ -324,6 +390,21 @@ do_execsql_test bitwise-or-float-float {
SELECT 1234.6 | 5432.2
} {5626}
foreach {testnum lhs rhs ans} {
1 'a' 'a' 0
2 'a' 10 10
3 10 'a' 10
4 'a' 11.0 11
5 11.0 'a' 11
7 '1' '2' 3
8 '1.0' '2' 3
9 '1.0' '4.0' 5
10 '1.0' '1.0' 1
11 '1' '1' 1
} {
do_execsql_test bitwise-or-text-$testnum "SELECT $lhs | $rhs" $::ans
}
do_execsql_test bitwise-and-int-agg-int-agg {
SELECT sum(id) | sum(id) from products
} {66}
@ -341,6 +422,14 @@ do_execsql_test bitwise-not-float {
SELECT ~823.34
} {-824}
do_execsql_test bitwise-not-text-float {
SELECT ~'823.34'
} {-824}
do_execsql_test bitwise-not-text-int {
SELECT ~'1234'
} {-1235}
do_execsql_test bitwise-not-scalar-float {
SELECT ~abs(693.9)
} {-694}