mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 01:58:16 +00:00
Fix arithmetic operations for text values
This commit is contained in:
parent
90d01f468f
commit
2b879a4f40
2 changed files with 146 additions and 0 deletions
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue