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) } } }
// ComputeBit computes the bitwise operation on two datums. func ComputeBit(op tipb.ExprType, left, right types.Datum) (types.Datum, error) { var result types.Datum a, err := types.CoerceArithmetic(left) if err != nil { return result, errors.Trace(err) } b, err := types.CoerceArithmetic(right) if err != nil { return result, errors.Trace(err) } a, b, err = types.CoerceDatum(a, b) if err != nil { return result, errors.Trace(err) } if a.IsNull() || b.IsNull() { return result, nil } switch op { case tipb.ExprType_BitAnd: return types.ComputeBitAnd(a, b) case tipb.ExprType_BitOr: return types.ComputeBitOr(a, b) case tipb.ExprType_BitXor: return types.ComputeBitXor(a, b) case tipb.ExprType_LeftShift: return types.ComputeLeftShift(a, b) case tipb.ExprType_RighShift: return types.ComputeRightShift(a, b) default: return result, errors.Errorf("Unknown binop type: %v", op) } }
// ComputeArithmetic computes the arithmetic operation on two datums. func ComputeArithmetic(op tipb.ExprType, left types.Datum, right types.Datum) (types.Datum, error) { var result types.Datum a, err := types.CoerceArithmetic(left) if err != nil { return result, errors.Trace(err) } b, err := types.CoerceArithmetic(right) if err != nil { return result, errors.Trace(err) } a, b = types.CoerceDatum(a, b) 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(a, b) default: return result, errors.Errorf("Unknown binop type: %v", op) } }
func (e *Evaluator) evalArithmetic(expr *tipb.Expr) (types.Datum, error) { var result types.Datum left, right, err := e.evalTwoChildren(expr) if err != nil { return result, errors.Trace(err) } a, err := types.CoerceArithmetic(left) if err != nil { return result, errors.Trace(err) } b, err := types.CoerceArithmetic(right) if err != nil { return result, errors.Trace(err) } a, b = types.CoerceDatum(a, b) if a.IsNull() || b.IsNull() { return result, nil } switch expr.GetTp() { case tipb.ExprType_Plus: return types.ComputePlus(a, b) case tipb.ExprType_Div: return types.ComputeDiv(a, b) default: return result, errors.Errorf("Unknown binop type: %v", expr.GetTp()) } }
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) } }
func (e *Evaluator) evalBitOps(expr *tipb.Expr) (types.Datum, error) { var result types.Datum if expr.GetTp() == tipb.ExprType_BitNeg { if len(expr.Children) != 1 { err := ErrInvalid.Gen("BitNeg(~) need 1 operand but got %d", len(expr.Children)) return result, err } operand, err := e.Eval(expr.Children[0]) if err != nil { return types.Datum{}, errors.Trace(err) } a, err := types.CoerceArithmetic(operand) if err != nil { return result, errors.Trace(err) } return types.ComputeBitNeg(a) } left, right, err := e.evalTwoChildren(expr) if err != nil { return result, errors.Trace(err) } return ComputeBit(expr.GetTp(), left, right) }