mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-07 10:14:21 +01:00
Merge 'Remainder fixes' from jachewz
This PR should close two related issues: ## 1. Remainder operand with lhs as text Before: ``` limbo> SELECT 10 % '3'; ┌──────────┐ │ 10 % '3' │ ├──────────┤ │ 3 │ └──────────┘ ``` sqlite: ``` sqlite> SELECT 10 % '3'; 1 ``` After: ``` limbo> SELECT 10 % '3'; ┌──────────┐ │ 10 % '3' │ ├──────────┤ │ 1 │ └──────────┘ ``` ## Overflow when min int64 % -1 Before: ``` limbo> SELECT -9223372036854775808 % -1; thread 'main' panicked at core/vdbe/insn.rs:974:37: attempt to calculate the remainder with overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` sqlite: ``` sqlite> SELECT -9223372036854775808 % -1; 0 ``` After: ``` limbo> SELECT -9223372036854775808 % -1; ┌─────────────────────────────┐ │ - 9223372036854775808 % - 1 │ ├─────────────────────────────┤ │ 0 │ └─────────────────────────────┘ ``` Tests for these cases are also added, and the `%` operator tests in `math.test` were renamed to `remainder-` instead of `mod-` to differentiate from tests for the `mod()` function. Closes #1172 Closes #1267
This commit is contained in:
@@ -971,7 +971,7 @@ pub fn exec_remainder(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
if rhs == &0 {
|
||||
OwnedValue::Null
|
||||
} else {
|
||||
OwnedValue::Integer(lhs % rhs)
|
||||
OwnedValue::Integer(lhs % rhs.abs())
|
||||
}
|
||||
}
|
||||
(OwnedValue::Float(lhs), OwnedValue::Float(rhs)) => {
|
||||
@@ -979,14 +979,14 @@ pub fn exec_remainder(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
if rhs_int == 0 {
|
||||
OwnedValue::Null
|
||||
} else {
|
||||
OwnedValue::Float(((*lhs as i64) % rhs_int) as f64)
|
||||
OwnedValue::Float(((*lhs as i64) % rhs_int.abs()) as f64)
|
||||
}
|
||||
}
|
||||
(OwnedValue::Float(lhs), OwnedValue::Integer(rhs)) => {
|
||||
if rhs == &0 {
|
||||
OwnedValue::Null
|
||||
} else {
|
||||
OwnedValue::Float(((*lhs as i64) % rhs) as f64)
|
||||
OwnedValue::Float(((*lhs as i64) % rhs.abs()) as f64)
|
||||
}
|
||||
}
|
||||
(OwnedValue::Integer(lhs), OwnedValue::Float(rhs)) => {
|
||||
@@ -994,16 +994,19 @@ pub fn exec_remainder(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
|
||||
if rhs_int == 0 {
|
||||
OwnedValue::Null
|
||||
} else {
|
||||
OwnedValue::Float((lhs % rhs_int) as f64)
|
||||
OwnedValue::Float((lhs % rhs_int.abs()) as f64)
|
||||
}
|
||||
}
|
||||
(OwnedValue::Text(lhs), OwnedValue::Text(rhs)) => exec_remainder(
|
||||
&cast_text_to_numeric(lhs.as_str()),
|
||||
&cast_text_to_numeric(rhs.as_str()),
|
||||
),
|
||||
(OwnedValue::Text(text), other) | (other, OwnedValue::Text(text)) => {
|
||||
(OwnedValue::Text(text), other) => {
|
||||
exec_remainder(&cast_text_to_numeric(text.as_str()), other)
|
||||
}
|
||||
(other, OwnedValue::Text(text)) => {
|
||||
exec_remainder(other, &cast_text_to_numeric(text.as_str()))
|
||||
}
|
||||
other => todo!("remainder not implemented for: {:?} {:?}", lhs, other),
|
||||
}
|
||||
}
|
||||
@@ -1685,10 +1688,15 @@ mod tests {
|
||||
(OwnedValue::Float(12.0), OwnedValue::Float(0.0)),
|
||||
(OwnedValue::Float(12.0), OwnedValue::Integer(0)),
|
||||
(OwnedValue::Integer(12), OwnedValue::Float(0.0)),
|
||||
(OwnedValue::Integer(i64::MIN), OwnedValue::Integer(-1)),
|
||||
(OwnedValue::Integer(12), OwnedValue::Integer(3)),
|
||||
(OwnedValue::Float(12.0), OwnedValue::Float(3.0)),
|
||||
(OwnedValue::Float(12.0), OwnedValue::Integer(3)),
|
||||
(OwnedValue::Integer(12), OwnedValue::Float(3.0)),
|
||||
(OwnedValue::Integer(12), OwnedValue::Integer(-3)),
|
||||
(OwnedValue::Float(12.0), OwnedValue::Float(-3.0)),
|
||||
(OwnedValue::Float(12.0), OwnedValue::Integer(-3)),
|
||||
(OwnedValue::Integer(12), OwnedValue::Float(-3.0)),
|
||||
(
|
||||
OwnedValue::Text(Text::from_str("12.0")),
|
||||
OwnedValue::Text(Text::from_str("3.0")),
|
||||
@@ -1699,7 +1707,7 @@ mod tests {
|
||||
),
|
||||
(
|
||||
OwnedValue::Float(12.0),
|
||||
OwnedValue::Text(Text::from_str("12.0")),
|
||||
OwnedValue::Text(Text::from_str("3.0")),
|
||||
),
|
||||
];
|
||||
let outputs = vec![
|
||||
@@ -1713,6 +1721,11 @@ mod tests {
|
||||
OwnedValue::Null,
|
||||
OwnedValue::Null,
|
||||
OwnedValue::Null,
|
||||
OwnedValue::Float(0.0),
|
||||
OwnedValue::Integer(0),
|
||||
OwnedValue::Float(0.0),
|
||||
OwnedValue::Float(0.0),
|
||||
OwnedValue::Float(0.0),
|
||||
OwnedValue::Integer(0),
|
||||
OwnedValue::Float(0.0),
|
||||
OwnedValue::Float(0.0),
|
||||
|
||||
@@ -1309,54 +1309,75 @@ do_execsql_test log-int-null {
|
||||
SELECT log(5, null)
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-int-null {
|
||||
do_execsql_test remainder-int-null {
|
||||
SELECT 183 % null
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-int-0 {
|
||||
do_execsql_test remainder-int-0 {
|
||||
SELECT 183 % 0
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-int-int {
|
||||
do_execsql_test remainder-int-int {
|
||||
SELECT 183 % 10
|
||||
} { 3 }
|
||||
|
||||
do_execsql_test mod-int-float {
|
||||
do_execsql_test remainder-int-float {
|
||||
SELECT 38 % 10.35
|
||||
} { 8.0 }
|
||||
|
||||
do_execsql_test mod-float-int {
|
||||
do_execsql_test remainder-float-int {
|
||||
SELECT 38.43 % 13
|
||||
} { 12.0 }
|
||||
|
||||
do_execsql_test mod-0-float {
|
||||
do_execsql_test remainder-0-float {
|
||||
SELECT 0 % 12.0
|
||||
} { 0.0 }
|
||||
|
||||
do_execsql_test mod-float-0 {
|
||||
do_execsql_test remainder-float-0 {
|
||||
SELECT 23.14 % 0
|
||||
} {}
|
||||
|
||||
do_execsql_test mod-float-float {
|
||||
do_execsql_test remainder-float-float {
|
||||
SELECT 23.14 % 12.0
|
||||
} { 11.0 }
|
||||
|
||||
do_execsql_test mod-float-agg {
|
||||
do_execsql_test remainder-float-agg {
|
||||
SELECT 23.14 % sum(id) from products
|
||||
} { 23.0 }
|
||||
|
||||
do_execsql_test mod-int-agg {
|
||||
do_execsql_test remainder-int-agg {
|
||||
SELECT 17 % sum(id) from users
|
||||
} { 17 }
|
||||
|
||||
do_execsql_test mod-agg-int {
|
||||
do_execsql_test remainder-agg-int {
|
||||
SELECT count(*) % 17 from users
|
||||
} { 4 }
|
||||
|
||||
do_execsql_test mod-agg-float {
|
||||
do_execsql_test remainder-agg-float {
|
||||
SELECT count(*) % 2.43 from users
|
||||
} { 0.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 '10' '3' 1
|
||||
8 '10.0' '3' 1.0
|
||||
9 '10.0' -3 1.0
|
||||
} {
|
||||
do_execsql_test remainder-text-$testnum "SELECT $lhs % $rhs" $::ans
|
||||
}
|
||||
|
||||
foreach {testnum lhs rhs ans} {
|
||||
1 '-9223372036854775808' '-1' 0
|
||||
2 -9223372036854775808 -1 0
|
||||
3 -9223372036854775809 -1 0.0
|
||||
} {
|
||||
do_execsql_test remainder-overflow-$testnum "SELECT $lhs % $rhs" $::ans
|
||||
}
|
||||
|
||||
do_execsql_test comp-float-float {
|
||||
SELECT 0.0 = 0.0
|
||||
} { 1 }
|
||||
|
||||
Reference in New Issue
Block a user