New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

coprocessor, dag: support decode Time from tipb.Expr #2199

Merged
merged 43 commits into from Aug 28, 2017
Commits
Jump to file or symbol
Failed to load files and symbols.
+82 −47
Diff settings

Always

Just for now

Viewing a subset of changes. View all
@@ -12,8 +12,6 @@
// limitations under the License.
use std::{f64, i64, u64};
use std::ops::Neg;
use std::num::Wrapping;
use std::borrow::Cow;
use coprocessor::codec::{mysql, Datum};
use coprocessor::codec::mysql::Decimal;
@@ -38,26 +36,29 @@ impl FnCall {
let lhs = try_opt!(self.children[0].eval_decimal(ctx, row));
let rhs = try_opt!(self.children[1].eval_decimal(ctx, row));
let result: Result<Decimal> = (lhs.as_ref() + rhs.as_ref()).into();
result.map(Cow::Owned).map(Some)
result.map(|t| Some(Cow::Owned(t)))
}
pub fn plus_int(&self, ctx: &StatementContext, row: &[Datum]) -> Result<Option<i64>> {
let lhs = try_opt!(self.children[0].eval_int(ctx, row));
let rhs = try_opt!(self.children[1].eval_int(ctx, row));
let lus = mysql::has_unsigned_flag(self.children[0].get_tp().get_flag());
let rus = mysql::has_unsigned_flag(self.children[1].get_tp().get_flag());
let res_us = match (lus | (lhs >= 0), rus | (rhs >= 0)) {
(true, true) => {
try!((lhs as u64).checked_add(rhs as u64).ok_or(Error::Overflow));
true
}
(false, false) => try!(lhs.checked_add(rhs).ok_or(Error::Overflow)) > 0,
(true, false) if lhs as u64 > i64::MAX as u64 => true,
(false, true) if rhs as u64 > i64::MAX as u64 => true,
_ => false,
let res = match (lus, rus) {
(true, true) => (lhs as u64).checked_add(rhs as u64).map(|t| t as i64),
(true, false) => if rhs >= 0 {
(lhs as u64).checked_add(rhs as u64).map(|t| t as i64)
} else {
(lhs as u64).checked_sub(opp_neg!(rhs)).map(|t| t as i64)
},
(false, true) => if lhs >= 0 {
(lhs as u64).checked_add(rhs as u64).map(|t| t as i64)
} else {
(rhs as u64).checked_sub(opp_neg!(lhs)).map(|t| t as i64)
},
(false, false) => lhs.checked_add(rhs),
};
let us = mysql::has_unsigned_flag(self.tp.get_flag());
check_integer_overflow(us, (Wrapping(lhs) + Wrapping(rhs)).0, res_us)
res.ok_or(Error::Overflow).map(Some)
}
pub fn minus_real(&self, ctx: &StatementContext, row: &[Datum]) -> Result<Option<f64>> {
@@ -86,31 +87,21 @@ impl FnCall {
let rhs = try_opt!(self.children[1].eval_int(ctx, row));
let lus = mysql::has_unsigned_flag(self.children[0].get_tp().get_flag());
let rus = mysql::has_unsigned_flag(self.children[1].get_tp().get_flag());
let res_us = match (lus, rus) {
(true, true) => {
try!((lhs as u64).checked_sub(rhs as u64).ok_or(Error::Overflow));
true
}
let res = match (lus, rus) {
(true, true) => (lhs as u64).checked_sub(rhs as u64).map(|t| t as i64),
(true, false) => if rhs >= 0 {
lhs as u64 > rhs as u64
(lhs as u64).checked_sub(rhs as u64).map(|t| t as i64)
} else {
try!((lhs as u64).checked_add(-rhs as u64).ok_or(Error::Overflow));
true
(lhs as u64).checked_add(opp_neg!(rhs)).map(|t| t as i64)
},
(false, true) => {
let l = (lhs - i64::MIN) as u64;
try!(l.checked_sub(rhs as u64).ok_or(Error::Overflow));
false
}
(false, false) => if lhs > 0 && rhs < 0 {
true
(false, true) => if lhs >= 0 {
(lhs as u64).checked_sub(rhs as u64).map(|t| t as i64)
} else {
try!(lhs.checked_sub(rhs).ok_or(Error::Overflow));
false
None
},
(false, false) => lhs.checked_sub(rhs),
};
let us = mysql::has_unsigned_flag(self.tp.get_flag());
check_integer_overflow(us, (Wrapping(lhs) - Wrapping(rhs)).0, res_us)
res.ok_or(Error::Overflow).map(Some)
}
pub fn multiply_real(&self, ctx: &StatementContext, row: &[Datum]) -> Result<Option<f64>> {
@@ -144,21 +135,21 @@ impl FnCall {
let (mut l, mut r) = (lhs as u64, rhs as u64);
if !lus && lhs < 0 {
a_neg = true;
l = Wrapping(lhs).neg().0 as u64;
l = opp_neg!(lhs);
}
if !rus && rhs < 0 {
b_neg = true;
r = Wrapping(rhs).neg().0 as u64;
r = opp_neg!(rhs);
}
let res = try!(l.checked_mul(r).ok_or(Error::Overflow));
let us = mysql::has_unsigned_flag(self.tp.get_flag());
if a_neg != b_neg {
try!((i64::MAX as u64).checked_sub(res).ok_or(Error::Overflow));
if (i64::MAX as u64) < res {
return Err(Error::Overflow);
}
let res = try!((res as i64).checked_neg().ok_or(Error::Overflow));
check_integer_overflow(us, res, false)
Ok(Some(res))
} else {
check_integer_overflow(us, (res as i64), true)
Ok(Some(res as i64))
}
}
}
@@ -209,12 +200,24 @@ mod test {
Datum::I64(1),
Datum::I64(13),
),
(
ScalarFuncSig::PlusInt,
Datum::I64(i64::MIN),
Datum::U64(i64::MAX as u64 + 1),
Datum::U64(0),
),
(
ScalarFuncSig::MinusInt,
Datum::I64(12),
Datum::I64(1),
Datum::I64(11),
),
(
ScalarFuncSig::MinusInt,
Datum::U64(0),
Datum::I64(i64::MIN),
Datum::U64(i64::MAX as u64 + 1),
),
(
ScalarFuncSig::MultiplyInt,
Datum::I64(12),
@@ -74,15 +74,29 @@ impl FnCall {
ScalarFuncSig::MinusInt |
ScalarFuncSig::MultiplyReal |
ScalarFuncSig::MultiplyDecimal |
ScalarFuncSig::MultiplyInt => (2, 2),
ScalarFuncSig::MultiplyInt |
ScalarFuncSig::LogicalAnd |
ScalarFuncSig::LogicalOr |
ScalarFuncSig::LogicalXor => (2, 2),
ScalarFuncSig::CastIntAsInt |
ScalarFuncSig::CastIntAsReal |
ScalarFuncSig::CastIntAsString |
ScalarFuncSig::CastIntAsDecimal |
ScalarFuncSig::CastIntAsTime |
ScalarFuncSig::CastIntAsDuration |
ScalarFuncSig::CastIntAsJson => (1, 1),
ScalarFuncSig::CastIntAsJson |
ScalarFuncSig::UnaryNot |
ScalarFuncSig::IntIsFalse |
ScalarFuncSig::IntIsNull |
ScalarFuncSig::RealIsTrue |
ScalarFuncSig::RealIsNull |
ScalarFuncSig::DecimalIsTrue |
ScalarFuncSig::DecimalIsNull |
ScalarFuncSig::StringIsNull |
ScalarFuncSig::TimeIsNull |
ScalarFuncSig::DurationIsNull => (1, 1),
_ => unimplemented!(),
};
if args < min_args || args > max_args {
Copy path View file
@@ -139,6 +139,7 @@ impl Expression {
}
}
#[cfg(test)]
#[inline]
fn mut_tp(&mut self) -> &mut FieldType {
match *self {
@@ -212,6 +213,20 @@ impl Expression {
ScalarFuncSig::PlusInt => f.plus_int(ctx, row),
ScalarFuncSig::MinusInt => f.minus_int(ctx, row),
ScalarFuncSig::MultiplyInt => f.multiply_int(ctx, row),
ScalarFuncSig::LogicalAnd => f.logical_and(ctx, row),
ScalarFuncSig::LogicalOr => f.logical_or(ctx, row),
ScalarFuncSig::LogicalXor => f.logical_xor(ctx, row),
ScalarFuncSig::UnaryNot => f.unary_not(ctx, row),
ScalarFuncSig::IntIsNull => f.int_is_null(ctx, row),
ScalarFuncSig::IntIsFalse => f.int_is_false(ctx, row),
ScalarFuncSig::RealIsTrue => f.real_is_true(ctx, row),
ScalarFuncSig::RealIsNull => f.real_is_null(ctx, row),
ScalarFuncSig::DecimalIsNull => f.decimal_is_null(ctx, row),
ScalarFuncSig::DecimalIsTrue => f.decimal_is_true(ctx, row),
ScalarFuncSig::StringIsNull => f.string_is_null(ctx, row),
ScalarFuncSig::TimeIsNull => f.time_is_null(ctx, row),
ScalarFuncSig::DurationIsNull => f.duration_is_null(ctx, row),
_ => Err(Error::Other("Unknown signature")),
},
@@ -226,7 +241,8 @@ impl Expression {
ScalarFuncSig::PlusReal => f.plus_real(ctx, row),
ScalarFuncSig::MinusReal => f.minus_real(ctx, row),
ScalarFuncSig::MultiplyReal => f.multiply_real(ctx, row),
_ => unimplemented!(),
_ => Err(Error::Other("Unknown signature")),
},
}
}
@@ -243,7 +259,8 @@ impl Expression {
ScalarFuncSig::PlusDecimal => f.plus_decimal(ctx, row),
ScalarFuncSig::MinusDecimal => f.minus_decimal(ctx, row),
ScalarFuncSig::MultiplyDecimal => f.multiply_decimal(ctx, row),
_ => unimplemented!(),
_ => Err(Error::Other("Unknown signature")),
},
}
}
@@ -298,7 +315,9 @@ impl Expression {
match *self {
Expression::Constant(ref constant) => constant.eval_json(),
Expression::ColumnRef(ref column) => column.eval_json(row),
_ => unimplemented!(),
Expression::ScalarFn(ref f) => match f.sig {
_ => Err(Error::Other("Unknown signature")),
},
}
}
@@ -397,14 +416,13 @@ impl Expression {
#[cfg(test)]
mod test {
use coprocessor::codec::Datum;
use coprocessor::codec::mysql::Decimal;
use coprocessor::select::xeval::evaluator::test::{col_expr, datum_expr};
use tipb::expression::{Expr, ExprType, FieldType, ScalarFuncSig};
use super::Expression;
#[inline]
pub fn str2dec(s: &str) -> Datum {
Datum::Dec(s.parse::<Decimal>().unwrap())
Datum::Dec(s.parse().unwrap())
}
pub fn fncall_expr(sig: ScalarFuncSig, children: &[Expr]) -> Expr {
ProTip! Use n and p to navigate between commits in a pull request.