func (e *Evaluator) handleComparisonOp(o *ast.BinaryOperationExpr) bool { a, b := types.Coerce(o.L.GetValue(), o.R.GetValue()) if types.IsNil(a) || types.IsNil(b) { // for <=>, if a and b are both nil, return true. // if a or b is nil, return false. if o.Op == opcode.NullEQ { if types.IsNil(a) || types.IsNil(b) { o.SetValue(oneI64) } else { o.SetValue(zeroI64) } } else { o.SetValue(nil) } return true } n, err := types.Compare(a, b) if err != nil { e.err = errors.Trace(err) return false } r, err := getCompResult(o.Op, n) if err != nil { e.err = errors.Trace(err) return false } if r { o.SetValue(oneI64) } else { o.SetValue(zeroI64) } return true }
func (o *BinaryOperation) coerceArithmetic2(a interface{}, b interface{}) (x interface{}, y interface{}, err error) { x, err = o.coerceArithmetic(a) if err != nil { return } y, err = o.coerceArithmetic(b) if err != nil { return } x, y = types.Coerce(x, y) return x, y, nil }
func (o *BinaryOperation) get2(ctx context.Context, args map[interface{}]interface{}) (x, y interface{}, err error) { x, err = o.L.Eval(ctx, args) if err != nil { err = o.traceErr(err) return } y, err = o.R.Eval(ctx, args) if err != nil { err = o.traceErr(err) return } x, y = types.Coerce(x, y) return x, y, nil }
// See https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_nullif func builtinNullIf(args []interface{}, m map[interface{}]interface{}) (interface{}, error) { // nullif(expr1, expr2) // returns null if expr1 = expr2 is true, otherwise returns expr1 v1 := args[0] v2 := args[1] if v1 == nil || v2 == nil { return v1, nil } // coerce for later eval compare x, y := types.Coerce(v1, v2) if n, err := evalCompare(x, y); err != nil || n == 0 { return nil, err } return v1, nil }
func (e *Evaluator) handleArithmeticOp(o *ast.BinaryOperationExpr) bool { a, err := coerceArithmetic(o.L.GetValue()) if err != nil { e.err = err return false } b, err := coerceArithmetic(o.R.GetValue()) if err != nil { e.err = err return false } a, b = types.Coerce(a, b) if a == nil || b == nil { // TODO: for <=>, if a and b are both nil, return true o.SetValue(nil) return true } // TODO: support logic division DIV var result interface{} switch o.Op { case opcode.Plus: result, e.err = computePlus(a, b) case opcode.Minus: result, e.err = computeMinus(a, b) case opcode.Mul: result, e.err = computeMul(a, b) case opcode.Div: result, e.err = computeDiv(a, b) case opcode.Mod: result, e.err = computeMod(a, b) case opcode.IntDiv: result, e.err = computeIntDiv(a, b) default: e.err = errors.Errorf("invalid op %v in arithmetic operation", o.Op) return false } o.SetValue(result) return e.err == nil }
func (e *Evaluator) handleArithmeticOp(o *ast.BinaryOperationExpr) bool { a, err := coerceArithmetic(types.RawData(o.L.GetValue())) if err != nil { e.err = errors.Trace(err) return false } b, err := coerceArithmetic(types.RawData(o.R.GetValue())) if err != nil { e.err = errors.Trace(err) return false } a, b = types.Coerce(a, b) if a == nil || b == nil { o.SetValue(nil) return true } var result interface{} switch o.Op { case opcode.Plus: result, e.err = computePlus(a, b) case opcode.Minus: result, e.err = computeMinus(a, b) case opcode.Mul: result, e.err = computeMul(a, b) case opcode.Div: result, e.err = computeDiv(a, b) case opcode.Mod: result, e.err = computeMod(a, b) case opcode.IntDiv: result, e.err = computeIntDiv(a, b) default: e.err = ErrInvalidOperation.Gen("invalid op %v in arithmetic operation", o.Op) return false } o.SetValue(result) return e.err == nil }
func (e *Evaluator) handleBitOp(o *ast.BinaryOperationExpr) bool { a, b := types.Coerce(o.L.GetValue(), o.R.GetValue()) if types.IsNil(a) || types.IsNil(b) { o.SetValue(nil) return true } x, err := types.ToInt64(a) if err != nil { e.err = errors.Trace(err) return false } y, err := types.ToInt64(b) if err != nil { e.err = errors.Trace(err) return false } // use a int64 for bit operator, return uint64 switch o.Op { case opcode.And: o.SetValue(uint64(x & y)) case opcode.Or: o.SetValue(uint64(x | y)) case opcode.Xor: o.SetValue(uint64(x ^ y)) case opcode.RightShift: o.SetValue(uint64(x) >> uint64(y)) case opcode.LeftShift: o.SetValue(uint64(x) << uint64(y)) default: e.err = ErrInvalidOperation.Gen("invalid op %v in bit operation", o.Op) return false } return true }