Beispiel #1
0
// ConvertDatumToDecimal converts datum to decimal.
func ConvertDatumToDecimal(d Datum) (*mysql.MyDecimal, error) {
	dec := new(mysql.MyDecimal)
	var err error
	switch d.Kind() {
	case KindInt64:
		dec.FromInt(d.GetInt64())
	case KindUint64:
		dec.FromUint(d.GetUint64())
	case KindFloat32:
		err = dec.FromFloat64(float64(d.GetFloat32()))
	case KindFloat64:
		err = dec.FromFloat64(d.GetFloat64())
	case KindString:
		err = dec.FromString(d.GetBytes())
	case KindMysqlDecimal:
		*dec = *d.GetMysqlDecimal()
	case KindMysqlHex:
		dec.FromInt(d.GetMysqlHex().Value)
	case KindMysqlBit:
		dec.FromUint(d.GetMysqlBit().Value)
	case KindMysqlEnum:
		dec.FromUint(d.GetMysqlEnum().Value)
	case KindMysqlSet:
		dec.FromUint(d.GetMysqlSet().Value)
	default:
		err = fmt.Errorf("can't convert %v to decimal", d.GetValue())
	}
	return dec, err
}
Beispiel #2
0
func (d *Datum) compareString(s string) (int, error) {
	switch d.k {
	case KindNull, KindMinNotNull:
		return -1, nil
	case KindMaxValue:
		return 1, nil
	case KindString, KindBytes:
		return CompareString(d.GetString(), s), nil
	case KindMysqlDecimal:
		dec := new(mysql.MyDecimal)
		err := dec.FromString([]byte(s))
		return d.GetMysqlDecimal().Compare(dec), err
	case KindMysqlTime:
		dt, err := mysql.ParseDatetime(s)
		return d.GetMysqlTime().Compare(dt), err
	case KindMysqlDuration:
		dur, err := mysql.ParseDuration(s, mysql.MaxFsp)
		return d.GetMysqlDuration().Compare(dur), err
	case KindMysqlBit:
		return CompareString(d.GetMysqlBit().ToString(), s), nil
	case KindMysqlHex:
		return CompareString(d.GetMysqlHex().ToString(), s), nil
	case KindMysqlSet:
		return CompareString(d.GetMysqlSet().String(), s), nil
	case KindMysqlEnum:
		return CompareString(d.GetMysqlEnum().String(), s), nil
	default:
		fVal, err := StrToFloat(s)
		if err != nil {
			return 0, err
		}
		return d.compareFloat64(fVal)
	}
}
Beispiel #3
0
func (d *Datum) compareMysqlDecimal(dec *mysql.MyDecimal) (int, error) {
	switch d.k {
	case KindMysqlDecimal:
		return d.GetMysqlDecimal().Compare(dec), nil
	case KindString, KindBytes:
		dDec := new(mysql.MyDecimal)
		err := dDec.FromString(d.GetBytes())
		return dDec.Compare(dec), err
	default:
		fVal, _ := dec.ToFloat64()
		return d.compareFloat64(fVal)
	}
}
Beispiel #4
0
func (s *testCodecSuite) TestDecimal(c *C) {
	defer testleak.AfterTest(c)()
	tbl := []string{
		"1234.00",
		"1234",
		"12.34",
		"12.340",
		"0.1234",
		"0.0",
		"0",
		"-0.0",
		"-0.0000",
		"-1234.00",
		"-1234",
		"-12.34",
		"-12.340",
		"-0.1234",
	}

	for _, t := range tbl {
		dec := new(mysql.MyDecimal)
		err := dec.FromString([]byte(t))
		c.Assert(err, IsNil)
		b, err := EncodeKey(nil, types.NewDatum(dec))
		c.Assert(err, IsNil)
		v, err := Decode(b)
		c.Assert(err, IsNil)
		c.Assert(v, HasLen, 1)
		vv := v[0].GetMysqlDecimal()
		c.Assert(vv.Compare(dec), Equals, 0)
	}

	tblCmp := []struct {
		Arg1 interface{}
		Arg2 interface{}
		Ret  int
	}{
		// Test for float type decimal.
		{"1234", "123400", -1},
		{"12340", "123400", -1},
		{"1234", "1234.5", -1},
		{"1234", "1234.0000", 0},
		{"1234", "12.34", 1},
		{"12.34", "12.35", -1},
		{"0.12", "0.1234", -1},
		{"0.1234", "12.3400", -1},
		{"0.1234", "0.1235", -1},
		{"0.123400", "12.34", -1},
		{"12.34000", "12.34", 0},
		{"0.01234", "0.01235", -1},
		{"0.1234", "0", 1},
		{"0.0000", "0", 0},
		{"0.0001", "0", 1},
		{"0.0001", "0.0000", 1},
		{"0", "-0.0000", 0},
		{"-0.0001", "0", -1},
		{"-0.1234", "0", -1},
		{"-0.1234", "-0.12", -1},
		{"-0.12", "-0.1234", 1},
		{"-0.12", "-0.1200", 0},
		{"-0.1234", "0.1234", -1},
		{"-1.234", "-12.34", 1},
		{"-0.1234", "-12.34", 1},
		{"-12.34", "1234", -1},
		{"-12.34", "-12.35", 1},
		{"-0.01234", "-0.01235", 1},
		{"-1234", "-123400", 1},
		{"-12340", "-123400", 1},

		// Test for int type decimal.
		{int64(-1), int64(1), -1},
		{int64(math.MaxInt64), int64(math.MinInt64), 1},
		{int64(math.MaxInt64), int64(math.MaxInt32), 1},
		{int64(math.MinInt32), int64(math.MaxInt16), -1},
		{int64(math.MinInt64), int64(math.MaxInt8), -1},
		{int64(0), int64(math.MaxInt8), -1},
		{int64(math.MinInt8), int64(0), -1},
		{int64(math.MinInt16), int64(math.MaxInt16), -1},
		{int64(1), int64(-1), 1},
		{int64(1), int64(0), 1},
		{int64(-1), int64(0), -1},
		{int64(0), int64(0), 0},
		{int64(math.MaxInt16), int64(math.MaxInt16), 0},

		// Test for uint type decimal.
		{uint64(0), uint64(0), 0},
		{uint64(1), uint64(0), 1},
		{uint64(0), uint64(1), -1},
		{uint64(math.MaxInt8), uint64(math.MaxInt16), -1},
		{uint64(math.MaxUint32), uint64(math.MaxInt32), 1},
		{uint64(math.MaxUint8), uint64(math.MaxInt8), 1},
		{uint64(math.MaxUint16), uint64(math.MaxInt32), -1},
		{uint64(math.MaxUint64), uint64(math.MaxInt64), 1},
		{uint64(math.MaxInt64), uint64(math.MaxUint32), 1},
		{uint64(math.MaxUint64), uint64(0), 1},
		{uint64(0), uint64(math.MaxUint64), -1},
	}

	for _, t := range tblCmp {
		d1 := types.NewDatum(t.Arg1)
		dec1, err := d1.ToDecimal()
		c.Assert(err, IsNil)
		d1.SetMysqlDecimal(dec1)
		d2 := types.NewDatum(t.Arg2)
		dec2, err := d2.ToDecimal()
		c.Assert(err, IsNil)
		d2.SetMysqlDecimal(dec2)

		d1.SetLength(30)
		d1.SetFrac(6)
		d2.SetLength(30)
		d2.SetFrac(6)
		b1, err := EncodeKey(nil, d1)
		c.Assert(err, IsNil)
		b2, err := EncodeKey(nil, d2)
		c.Assert(err, IsNil)

		ret := bytes.Compare(b1, b2)
		c.Assert(ret, Equals, t.Ret, Commentf("%v %x %x", t, b1, b2))
	}

	floats := []float64{-123.45, -123.40, -23.45, -1.43, -0.93, -0.4333, -0.068,
		-0.0099, 0, 0.001, 0.0012, 0.12, 1.2, 1.23, 123.3, 2424.242424}
	var decs [][]byte
	for i := range floats {
		dec := mysql.NewDecFromFloatForTest(floats[i])
		var d types.Datum
		d.SetLength(20)
		d.SetFrac(6)
		d.SetMysqlDecimal(dec)
		decs = append(decs, EncodeDecimal(nil, d))
	}
	for i := 0; i < len(decs)-1; i++ {
		cmp := bytes.Compare(decs[i], decs[i+1])
		c.Assert(cmp, LessEqual, 0)
	}
}