rowcodec: fix lose decimal precision during decode new row format to datum (#14631)

This commit is contained in:
lysu
2020-02-05 10:10:24 +08:00
committed by GitHub
parent ebc6a2d39d
commit 099782898e
3 changed files with 33 additions and 4 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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
}
}
)