// ComputeMinus computes the result of a-b. func ComputeMinus(a, b Datum) (d Datum, err error) { switch a.Kind() { case KindInt64: switch b.Kind() { case KindInt64: r, err1 := SubInt64(a.GetInt64(), b.GetInt64()) d.SetInt64(r) return d, errors.Trace(err1) case KindUint64: r, err1 := SubIntWithUint(a.GetInt64(), b.GetUint64()) d.SetUint64(r) return d, errors.Trace(err1) } case KindUint64: switch b.Kind() { case KindInt64: r, err1 := SubUintWithInt(a.GetUint64(), b.GetInt64()) d.SetUint64(r) return d, errors.Trace(err1) case KindUint64: r, err1 := SubUint64(a.GetUint64(), b.GetUint64()) d.SetUint64(r) return d, errors.Trace(err1) } case KindFloat64: switch b.Kind() { case KindFloat64: r := a.GetFloat64() - b.GetFloat64() d.SetFloat64(r) return d, nil } case KindMysqlDecimal: switch b.Kind() { case KindMysqlDecimal: r := new(mysql.MyDecimal) err = mysql.DecimalSub(a.GetMysqlDecimal(), b.GetMysqlDecimal(), r) d.SetMysqlDecimal(r) return d, err } } _, err = InvOp2(a.GetValue(), b.GetValue(), opcode.Minus) return d, errors.Trace(err) }
func (e *Evaluator) unaryOperation(u *ast.UnaryOperationExpr) bool { defer func() { if er := recover(); er != nil { e.err = errors.Errorf("%v", er) } }() aDatum := u.V.GetDatum() if aDatum.IsNull() { u.SetNull() return true } switch op := u.Op; op { case opcode.Not: n, err := aDatum.ToBool() if err != nil { e.err = errors.Trace(err) } else if n == 0 { u.SetInt64(1) } else { u.SetInt64(0) } case opcode.BitNeg: // for bit operation, we will use int64 first, then return uint64 n, err := aDatum.ToInt64() if err != nil { e.err = errors.Trace(err) return false } u.SetUint64(uint64(^n)) case opcode.Plus: switch aDatum.Kind() { case types.KindInt64, types.KindUint64, types.KindFloat64, types.KindFloat32, types.KindMysqlDuration, types.KindMysqlTime, types.KindString, types.KindMysqlDecimal, types.KindBytes, types.KindMysqlHex, types.KindMysqlBit, types.KindMysqlEnum, types.KindMysqlSet: u.SetDatum(*aDatum) default: e.err = ErrInvalidOperation return false } case opcode.Minus: switch aDatum.Kind() { case types.KindInt64: u.SetInt64(-aDatum.GetInt64()) case types.KindUint64: u.SetInt64(-int64(aDatum.GetUint64())) case types.KindFloat64: u.SetFloat64(-aDatum.GetFloat64()) case types.KindFloat32: u.SetFloat32(-aDatum.GetFloat32()) case types.KindMysqlDuration: var to = new(mysql.MyDecimal) var zero mysql.MyDecimal mysql.DecimalSub(&zero, aDatum.GetMysqlDuration().ToNumber(), to) u.SetMysqlDecimal(to) case types.KindMysqlTime: dec := aDatum.GetMysqlTime().ToNumber() var zero, to mysql.MyDecimal mysql.DecimalSub(&zero, dec, &to) u.SetMysqlDecimal(&to) case types.KindString, types.KindBytes: f, err := types.StrToFloat(aDatum.GetString()) e.err = errors.Trace(err) u.SetFloat64(-f) case types.KindMysqlDecimal: dec := aDatum.GetMysqlDecimal() var zero, to mysql.MyDecimal mysql.DecimalSub(&zero, dec, &to) u.SetMysqlDecimal(&to) case types.KindMysqlHex: u.SetFloat64(-aDatum.GetMysqlHex().ToNumber()) case types.KindMysqlBit: u.SetFloat64(-aDatum.GetMysqlBit().ToNumber()) case types.KindMysqlEnum: u.SetFloat64(-aDatum.GetMysqlEnum().ToNumber()) case types.KindMysqlSet: u.SetFloat64(-aDatum.GetMysqlSet().ToNumber()) default: e.err = ErrInvalidOperation return false } default: e.err = ErrInvalidOperation return false } return true }
func unaryOpFactory(op opcode.Op) BuiltinFunc { return func(args []types.Datum, _ context.Context) (d types.Datum, err error) { defer func() { if er := recover(); er != nil { err = errors.Errorf("%v", er) } }() aDatum := args[0] if aDatum.IsNull() { return } switch op { case opcode.Not: var n int64 n, err = aDatum.ToBool() if err != nil { err = errors.Trace(err) } else if n == 0 { d.SetInt64(1) } else { d.SetInt64(0) } case opcode.BitNeg: var n int64 // for bit operation, we will use int64 first, then return uint64 n, err = aDatum.ToInt64() if err != nil { return d, errors.Trace(err) } d.SetUint64(uint64(^n)) case opcode.Plus: switch aDatum.Kind() { case types.KindInt64, types.KindUint64, types.KindFloat64, types.KindFloat32, types.KindMysqlDuration, types.KindMysqlTime, types.KindString, types.KindMysqlDecimal, types.KindBytes, types.KindMysqlHex, types.KindMysqlBit, types.KindMysqlEnum, types.KindMysqlSet: d = aDatum default: return d, ErrInvalidOperation.Gen("Unsupported type %v for op.Plus", aDatum.Kind()) } case opcode.Minus: switch aDatum.Kind() { case types.KindInt64: d.SetInt64(-aDatum.GetInt64()) case types.KindUint64: d.SetInt64(-int64(aDatum.GetUint64())) case types.KindFloat64: d.SetFloat64(-aDatum.GetFloat64()) case types.KindFloat32: d.SetFloat32(-aDatum.GetFloat32()) case types.KindMysqlDuration: dec := new(mysql.MyDecimal) err = mysql.DecimalSub(new(mysql.MyDecimal), aDatum.GetMysqlDuration().ToNumber(), dec) d.SetMysqlDecimal(dec) case types.KindMysqlTime: dec := new(mysql.MyDecimal) err = mysql.DecimalSub(new(mysql.MyDecimal), aDatum.GetMysqlTime().ToNumber(), dec) d.SetMysqlDecimal(dec) case types.KindString, types.KindBytes: f, err1 := types.StrToFloat(aDatum.GetString()) err = errors.Trace(err1) d.SetFloat64(-f) case types.KindMysqlDecimal: dec := new(mysql.MyDecimal) err = mysql.DecimalSub(new(mysql.MyDecimal), aDatum.GetMysqlDecimal(), dec) d.SetMysqlDecimal(dec) case types.KindMysqlHex: d.SetFloat64(-aDatum.GetMysqlHex().ToNumber()) case types.KindMysqlBit: d.SetFloat64(-aDatum.GetMysqlBit().ToNumber()) case types.KindMysqlEnum: d.SetFloat64(-aDatum.GetMysqlEnum().ToNumber()) case types.KindMysqlSet: d.SetFloat64(-aDatum.GetMysqlSet().ToNumber()) default: return d, ErrInvalidOperation.Gen("Unsupported type %v for op.Minus", aDatum.Kind()) } default: return d, ErrInvalidOperation.Gen("Unsupported op %v for unary op", op) } return } }