func arithmeticFuncFactory(op opcode.Op) BuiltinFunc { return func(args []types.Datum, _ context.Context) (d types.Datum, err error) { a, err := types.CoerceArithmetic(args[0]) if err != nil { return d, errors.Trace(err) } b, err := types.CoerceArithmetic(args[1]) if err != nil { return d, errors.Trace(err) } a, b = types.CoerceDatum(a, b) if a.IsNull() || b.IsNull() { return } switch op { case opcode.Plus: return types.ComputePlus(a, b) case opcode.Minus: return types.ComputeMinus(a, b) case opcode.Mul: return types.ComputeMul(a, b) case opcode.Div: return types.ComputeDiv(a, b) case opcode.Mod: return types.ComputeMod(a, b) case opcode.IntDiv: return types.ComputeIntDiv(a, b) default: return d, ErrInvalidOperation.Gen("invalid op %v in arithmetic operation", op) } } }
func (e *Evaluator) handleArithmeticOp(o *ast.BinaryOperationExpr) bool { a, err := types.CoerceArithmetic(e.sc, *o.L.GetDatum()) if err != nil { e.err = errors.Trace(err) return false } b, err := types.CoerceArithmetic(e.sc, *o.R.GetDatum()) if err != nil { e.err = errors.Trace(err) return false } a, b, err = types.CoerceDatum(e.sc, a, b) if err != nil { e.err = errors.Trace(err) return false } if a.IsNull() || b.IsNull() { o.SetNull() return true } var result types.Datum switch o.Op { case opcode.Plus: result, e.err = types.ComputePlus(a, b) case opcode.Minus: result, e.err = types.ComputeMinus(a, b) case opcode.Mul: result, e.err = types.ComputeMul(a, b) case opcode.Div: result, e.err = types.ComputeDiv(e.sc, a, b) case opcode.Mod: result, e.err = types.ComputeMod(e.sc, a, b) case opcode.IntDiv: result, e.err = types.ComputeIntDiv(e.sc, a, b) default: e.err = ErrInvalidOperation.Gen("invalid op %v in arithmetic operation", o.Op) return false } o.SetDatum(result) return e.err == nil }
// ComputeArithmetic computes the arithmetic operation on two datums. func ComputeArithmetic(sc *variable.StatementContext, op tipb.ExprType, left types.Datum, right types.Datum) (types.Datum, error) { var result types.Datum a, err := types.CoerceArithmetic(sc, left) if err != nil { return result, errors.Trace(err) } b, err := types.CoerceArithmetic(sc, right) if err != nil { return result, errors.Trace(err) } a, b, err = types.CoerceDatum(sc, a, b) if err != nil { return result, errors.Trace(err) } if a.IsNull() || b.IsNull() { return result, nil } switch op { case tipb.ExprType_Plus: return types.ComputePlus(a, b) case tipb.ExprType_Div: return types.ComputeDiv(sc, a, b) case tipb.ExprType_Minus: return types.ComputeMinus(a, b) case tipb.ExprType_Mul: return types.ComputeMul(a, b) case tipb.ExprType_IntDiv: return types.ComputeIntDiv(sc, a, b) case tipb.ExprType_Mod: return types.ComputeMod(sc, a, b) default: return result, errors.Errorf("Unknown binop type: %v", op) } }