mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-25 20:14:21 +01:00
Merge 'Fix integer overflow output to be same as sqlite3' from Vrishabh
In sqlite3, before arithmetic operation is done, it first checks if the operation dosent overflow and then does the operation. In case it overflows it would covert the arguments into floats and then does the operation as [per code](https://github.com/sqlite/sqlite/blob/ded37f337b 7b2e916657a83732aaec40eb146282/src/vdbe.c#L1875) . I have done the same behaviour for limbo. Closes #612
This commit is contained in:
@@ -507,7 +507,14 @@ pub fn exec_add(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
rhs = agg.final_value();
|
||||
}
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Integer(lhs + rhs),
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
|
||||
let result = lhs.overflowing_add(*rhs);
|
||||
if result.1 {
|
||||
OwnedValue::Float(*lhs as f64 + *rhs as f64)
|
||||
} else {
|
||||
OwnedValue::Integer(result.0)
|
||||
}
|
||||
}
|
||||
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(lhs + rhs),
|
||||
(OwnedValue::Float(f), OwnedValue::Integer(i))
|
||||
| (OwnedValue::Integer(i), OwnedValue::Float(f)) => OwnedValue::Float(*f + *i as f64),
|
||||
@@ -531,7 +538,14 @@ pub fn exec_subtract(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
rhs = agg.final_value();
|
||||
}
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Integer(lhs - rhs),
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
|
||||
let result = lhs.overflowing_sub(*rhs);
|
||||
if result.1 {
|
||||
OwnedValue::Float(*lhs as f64 - *rhs as f64)
|
||||
} else {
|
||||
OwnedValue::Integer(result.0)
|
||||
}
|
||||
}
|
||||
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(lhs - rhs),
|
||||
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Float(lhs - *rhs as f64),
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(*lhs as f64 - rhs),
|
||||
@@ -557,7 +571,14 @@ pub fn exec_multiply(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
rhs = agg.final_value();
|
||||
}
|
||||
match (lhs, rhs) {
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Integer(lhs * rhs),
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
|
||||
let result = lhs.overflowing_mul(*rhs);
|
||||
if result.1 {
|
||||
OwnedValue::Float(*lhs as f64 * *rhs as f64)
|
||||
} else {
|
||||
OwnedValue::Integer(result.0)
|
||||
}
|
||||
}
|
||||
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(lhs * rhs),
|
||||
(OwnedValue::Integer(i), OwnedValue::Float(f))
|
||||
| (OwnedValue::Float(f), OwnedValue::Integer(i)) => OwnedValue::Float(*i as f64 * { *f }),
|
||||
@@ -583,7 +604,14 @@ pub fn exec_divide(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
|
||||
}
|
||||
match (lhs, rhs) {
|
||||
(_, OwnedValue::Integer(0)) | (_, OwnedValue::Float(0.0)) => OwnedValue::Null,
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Integer(lhs / rhs),
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
|
||||
let result = lhs.overflowing_div(*rhs);
|
||||
if result.1 {
|
||||
OwnedValue::Float(*lhs as f64 / *rhs as f64)
|
||||
} else {
|
||||
OwnedValue::Integer(result.0)
|
||||
}
|
||||
}
|
||||
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(lhs / rhs),
|
||||
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => OwnedValue::Float(lhs / *rhs as f64),
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => OwnedValue::Float(*lhs as f64 / rhs),
|
||||
|
||||
@@ -6,6 +6,7 @@ source $testdir/tester.tcl
|
||||
# Tolerance for floating point comparisons
|
||||
# FIXME: When Limbo's floating point presentation matches to SQLite, this could/should be removed
|
||||
set tolerance 1e-13
|
||||
set overflow_tolerance 5e4
|
||||
|
||||
do_execsql_test add-int {
|
||||
SELECT 10 + 1
|
||||
@@ -44,6 +45,19 @@ foreach {testnum lhs rhs ans} {
|
||||
do_execsql_test add-text-$testnum "SELECT $lhs + $rhs" $::ans
|
||||
}
|
||||
|
||||
foreach {testnum lhs rhs ans} {
|
||||
1 '9223372036854775807' '0' 9223372036854775807
|
||||
2 '9223372036854775807' '1' 9.22337203685478e+18
|
||||
3 9223372036854775807 0 9223372036854775807
|
||||
4 9223372036854775807 1 9.22337203685478e+18
|
||||
5 '-9223372036854775808' '0' -9223372036854775808
|
||||
6 '-9223372036854775808' '-1' -9.22337203685478e+18
|
||||
7 -9223372036854775808 0 -9223372036854775808
|
||||
8 -9223372036854775808 -1 -9.22337203685478e+18
|
||||
} {
|
||||
do_execsql_test_tolerance add-overflow-$testnum "SELECT $lhs + $rhs" $::ans $overflow_tolerance
|
||||
}
|
||||
|
||||
do_execsql_test subtract-int {
|
||||
SELECT 10 - 1
|
||||
} {9}
|
||||
@@ -81,6 +95,19 @@ foreach {testnum lhs rhs ans} {
|
||||
do_execsql_test subtract-text-$testnum "SELECT $lhs - $rhs" $::ans
|
||||
}
|
||||
|
||||
foreach {testnum lhs rhs ans} {
|
||||
1 '9223372036854775807' '0' 9223372036854775807
|
||||
2 '9223372036854775807' '-1' 9.22337203685478e+18
|
||||
3 9223372036854775807 0 9223372036854775807
|
||||
4 9223372036854775807 -1 9.22337203685478e+18
|
||||
5 '-9223372036854775808' '0' -9223372036854775808
|
||||
6 '-9223372036854775808' '1' -9.22337203685478e+18
|
||||
7 -9223372036854775808 0 -9223372036854775808
|
||||
8 -9223372036854775808 1 -9.22337203685478e+18
|
||||
} {
|
||||
do_execsql_test_tolerance subtract-overflow-$testnum "SELECT $lhs - $rhs" $::ans $overflow_tolerance
|
||||
}
|
||||
|
||||
do_execsql_test multiply-int {
|
||||
SELECT 10 * 2
|
||||
} {20}
|
||||
@@ -122,6 +149,19 @@ foreach {testnum lhs rhs ans} {
|
||||
do_execsql_test multiply-text-$testnum "SELECT $lhs * $rhs" $::ans
|
||||
}
|
||||
|
||||
foreach {testnum lhs rhs ans} {
|
||||
1 '9223372036854775807' '1' 9223372036854775807
|
||||
2 '9223372036854775807' '2' 1.84467440737096e+19
|
||||
3 9223372036854775807 1 9223372036854775807
|
||||
4 9223372036854775807 2 1.84467440737096e+19
|
||||
5 '-9223372036854775808' '1' -9223372036854775808
|
||||
6 '-9223372036854775808' '2' -1.84467440737096e+19
|
||||
7 -9223372036854775808 1 -9223372036854775808
|
||||
8 -9223372036854775808 2 -1.84467440737096e+19
|
||||
} {
|
||||
do_execsql_test_tolerance multiply-overflow-$testnum "SELECT $lhs * $rhs" $::ans $overflow_tolerance
|
||||
}
|
||||
|
||||
do_execsql_test divide-int {
|
||||
SELECT 10 / 2
|
||||
} {5}
|
||||
@@ -183,6 +223,15 @@ foreach {testnum lhs rhs ans} {
|
||||
do_execsql_test divide-text-$testnum "SELECT $lhs / $rhs" $::ans
|
||||
}
|
||||
|
||||
foreach {testnum lhs rhs ans} {
|
||||
5 '-9223372036854775808' '0' {}
|
||||
6 '-9223372036854775808' '-1' 9.22337203685478e+18
|
||||
7 -9223372036854775808 0 {}
|
||||
8 -9223372036854775808 -1 9.22337203685478e+18
|
||||
} {
|
||||
do_execsql_test_tolerance divide-overflow-$testnum "SELECT $lhs / $rhs" $::ans $overflow_tolerance
|
||||
}
|
||||
|
||||
do_execsql_test add-agg-int {
|
||||
SELECT sum(id) + 10 from products
|
||||
} {76}
|
||||
|
||||
Reference in New Issue
Block a user