rowcodec: fix lose decimal precision during decode new row format to datum (#14631)
This commit is contained in:
@ -189,6 +189,13 @@ func (s *testSuite8) TestInsertOnDuplicateKey(c *C) {
|
||||
tk.MustExec(`insert into t1 values(4,14),(5,15),(6,16),(7,17),(8,18) on duplicate key update b=b+10`)
|
||||
c.Assert(tk.Se.AffectedRows(), Equals, uint64(7))
|
||||
tk.CheckLastMessage("Records: 5 Duplicates: 2 Warnings: 0")
|
||||
|
||||
// reproduce insert on duplicate key update bug under new row format.
|
||||
tk.MustExec(`drop table if exists t1`)
|
||||
tk.MustExec(`create table t1(c1 decimal(6,4), primary key(c1))`)
|
||||
tk.MustExec(`insert into t1 set c1 = 0.1`)
|
||||
tk.MustExec(`insert into t1 set c1 = 0.1 on duplicate key update c1 = 1`)
|
||||
tk.MustQuery(`select * from t1 use index(primary)`).Check(testkit.Rows(`1.0000`))
|
||||
}
|
||||
|
||||
func (s *testSuite3) TestUpdateDuplicateKey(c *C) {
|
||||
|
||||
@ -133,11 +133,13 @@ func (decoder *DatumMapDecoder) decodeColDatum(col *ColInfo, colData []byte) (ty
|
||||
mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob:
|
||||
d.SetBytes(colData)
|
||||
case mysql.TypeNewDecimal:
|
||||
_, dec, _, _, err := codec.DecodeDecimal(colData)
|
||||
_, dec, precision, frac, err := codec.DecodeDecimal(colData)
|
||||
if err != nil {
|
||||
return d, err
|
||||
}
|
||||
d.SetMysqlDecimal(dec)
|
||||
d.SetLength(precision)
|
||||
d.SetFrac(frac)
|
||||
case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp:
|
||||
var t types.Time
|
||||
t.SetType(uint8(col.Tp))
|
||||
@ -268,10 +270,18 @@ func (decoder *ChunkDecoder) decodeColToChunk(colIdx int, col *ColInfo, colData
|
||||
mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob:
|
||||
chk.AppendBytes(colIdx, colData)
|
||||
case mysql.TypeNewDecimal:
|
||||
_, dec, _, _, err := codec.DecodeDecimal(colData)
|
||||
_, dec, _, frac, err := codec.DecodeDecimal(colData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if col.Decimal != types.UnspecifiedLength && frac > col.Decimal {
|
||||
to := new(types.MyDecimal)
|
||||
err := dec.Round(to, col.Decimal, types.ModeHalfEven)
|
||||
if err != nil {
|
||||
return errors.Trace(err)
|
||||
}
|
||||
dec = to
|
||||
}
|
||||
chk.AppendMyDecimal(colIdx, dec)
|
||||
case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp:
|
||||
var t types.Time
|
||||
|
||||
@ -363,8 +363,8 @@ func (s *testSuite) TestTypesNewRowCodec(c *C) {
|
||||
{
|
||||
8,
|
||||
types.NewFieldType(mysql.TypeNewDecimal),
|
||||
types.NewDecimalDatum(types.NewDecFromStringForTest("1.99")),
|
||||
types.NewDecimalDatum(types.NewDecFromStringForTest("1.99")),
|
||||
withFrac(4)(withLen(6)(types.NewDecimalDatum(types.NewDecFromStringForTest("11.9900")))),
|
||||
withFrac(4)(withLen(6)(types.NewDecimalDatum(types.NewDecFromStringForTest("11.9900")))),
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
@ -775,4 +775,16 @@ var (
|
||||
getDatumPoint = func(d types.Datum) *types.Datum {
|
||||
return &d
|
||||
}
|
||||
withFrac = func(f int) func(d types.Datum) types.Datum {
|
||||
return func(d types.Datum) types.Datum {
|
||||
d.SetFrac(f)
|
||||
return d
|
||||
}
|
||||
}
|
||||
withLen = func(len int) func(d types.Datum) types.Datum {
|
||||
return func(d types.Datum) types.Datum {
|
||||
d.SetLength(len)
|
||||
return d
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user