diff --git a/src/coprocessor/codec/mysql/decimal.rs b/src/coprocessor/codec/mysql/decimal.rs index 6cd7ae6e41b..7a6720c46fb 100644 --- a/src/coprocessor/codec/mysql/decimal.rs +++ b/src/coprocessor/codec/mysql/decimal.rs @@ -14,7 +14,7 @@ use std::fmt::{self, Display, Formatter}; use std::str::{self, FromStr}; use std::io::Write; -use std::ops::{Add, Deref, DerefMut, Div, Mul, Rem, Sub}; +use std::ops::{Add, Deref, DerefMut, Div, Mul, Neg, Rem, Sub}; use std::{cmp, mem, i32, i64, u32, u64}; use std::cmp::Ordering; @@ -2024,6 +2024,17 @@ impl Rem for Decimal { } } +impl Neg for Decimal { + type Output = Decimal; + + fn neg(mut self) -> Decimal { + if !self.is_zero() { + self.negative = !self.negative; + } + self + } +} + #[cfg(test)] mod test { use super::*; @@ -2905,6 +2916,37 @@ mod test { } } + #[test] + fn test_neg() { + let cases = vec![ + ("123.45", "-123.45"), + ("1", "-1"), + ("1234500009876.5", "-1234500009876.5"), + ("1111.5551", "-1111.5551"), + ("0.555", "-0.555"), + ("0", "0"), + ("0.0", "0.0"), + ("0.00", "0.00"), + ]; + + for (pos, neg) in cases { + let pos_dec: Decimal = pos.parse().unwrap(); + let res = -pos_dec.clone(); + assert_eq!(format!("{}", res), neg); + assert!((&pos_dec + &res).is_zero()); + + let neg_dec: Decimal = neg.parse().unwrap(); + let res = -neg_dec.clone(); + assert_eq!(format!("{}", res), pos); + assert!((&neg_dec + &res).is_zero()); + } + + let max_dec = super::max_or_min_dec(false, 40, 20); + let min_dec = super::max_or_min_dec(true, 40, 20); + assert_eq!(min_dec, -max_dec.clone()); + assert_eq!(max_dec, -min_dec.clone()); + } + #[test] fn test_max_or_min_decimal() { let cases = vec![