From aecb7ba32fb79cb15761b269b2dd477eb342ca3b Mon Sep 17 00:00:00 2001 From: Shirly Date: Tue, 23 Jan 2018 15:29:35 +0800 Subject: [PATCH] executor/aggregate: convert int to decimal in sum (#2694) --- src/coprocessor/dag/executor/aggregate.rs | 46 ++++++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/src/coprocessor/dag/executor/aggregate.rs b/src/coprocessor/dag/executor/aggregate.rs index 58f9d5a37a1..e0878bd3674 100644 --- a/src/coprocessor/dag/executor/aggregate.rs +++ b/src/coprocessor/dag/executor/aggregate.rs @@ -15,6 +15,7 @@ use std::cmp::Ordering; use tipb::expression::ExprType; use coprocessor::codec::Datum; +use coprocessor::codec::mysql::Decimal; use coprocessor::Result; use super::super::expr::{eval_arith, EvalContext}; @@ -187,9 +188,15 @@ impl Sum { if a == Datum::Null { return Ok(false); } + + let v = match a { + Datum::I64(v) => Datum::Dec(Decimal::from(v)), + Datum::U64(v) => Datum::Dec(Decimal::from(v)), + v => v, + }; let res = match self.res.take() { - Some(b) => box_try!(eval_arith(ctx, a, b, Datum::checked_add)), - None => a, + Some(b) => box_try!(eval_arith(ctx, v, b, Datum::checked_add)), + None => v, }; self.res = Some(res); Ok(true) @@ -273,3 +280,38 @@ impl AggrFunc for Extremum { Ok(()) } } + +#[cfg(test)] +mod test { + use std::{i64, u64}; + use std::ops::Add; + use coprocessor::dag::expr::EvalContext; + + use super::*; + + #[test] + fn test_sum_int() { + let mut sum = Sum { res: None }; + let ctx = EvalContext::default(); + let v1 = Datum::I64(i64::MAX); + let v2 = Datum::I64(12); + let res = Decimal::from(i64::MAX).add(&Decimal::from(12)).unwrap(); + sum.update(&ctx, vec![v1]).unwrap(); + sum.update(&ctx, vec![v2]).unwrap(); + let v = sum.res.take().unwrap(); + assert_eq!(v, Datum::Dec(res)); + } + + #[test] + fn test_sum_uint() { + let mut sum = Sum { res: None }; + let ctx = EvalContext::default(); + let v1 = Datum::U64(u64::MAX); + let v2 = Datum::U64(12); + let res = Decimal::from(u64::MAX).add(&Decimal::from(12)).unwrap(); + sum.update(&ctx, vec![v1]).unwrap(); + sum.update(&ctx, vec![v2]).unwrap(); + let v = sum.res.take().unwrap(); + assert_eq!(v, Datum::Dec(res)); + } +}