Skip to content

Commit

Permalink
types/data: the bit data type should be treat as uint64 (#1195… (#12423)
Browse files Browse the repository at this point in the history
  • Loading branch information
sre-bot authored and zz-jason committed Sep 27, 2019
1 parent c5fdec7 commit b736230
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
19 changes: 19 additions & 0 deletions executor/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
. "github.com/pingcap/check"
"github.com/pingcap/parser/terror"
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/testkit"
)

Expand Down Expand Up @@ -573,3 +574,21 @@ func (s *testSuite3) TestPartitionInsertOnDuplicate(c *C) {
tk.MustExec("insert into t3 values (1,2,3,4,5),(6,2,3,4,6) on duplicate key update e = e + values(e)")
tk.MustQuery("select * from t3").Check(testkit.Rows("1 2 3 4 16"))
}

func (s *testSuite3) TestBit(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec(`use test`)
tk.MustExec(`create table t1 (a bit(3))`)
_, err := tk.Exec("insert into t1 values(-1)")
c.Assert(types.ErrDataTooLong.Equal(err), IsTrue)
c.Assert(err.Error(), Matches, ".*Data too long for column 'a' at.*")
_, err = tk.Exec("insert into t1 values(9)")
c.Assert(err.Error(), Matches, ".*Data too long for column 'a' at.*")

tk.MustExec(`create table t64 (a bit(64))`)
tk.MustExec("insert into t64 values(-1)")
tk.MustExec("insert into t64 values(18446744073709551615)") // 2^64 - 1
_, err = tk.Exec("insert into t64 values(18446744073709551616)") // z^64
c.Assert(err.Error(), Matches, ".*Out of range value for column 'a' at.*")

}
6 changes: 5 additions & 1 deletion types/datum.go
Original file line number Diff line number Diff line change
Expand Up @@ -1215,12 +1215,16 @@ func (d *Datum) convertToMysqlBit(sc *stmtctx.StatementContext, target *FieldTyp
switch d.k {
case KindString, KindBytes:
uintValue, err = BinaryLiteral(d.b).ToInt(sc)
case KindInt64:
// if input kind is int64 (signed), when trans to bit, we need to treat it as unsigned
d.k = KindUint64
fallthrough
default:
uintDatum, err1 := d.convertToUint(sc, target)
uintValue, err = uintDatum.GetUint64(), err1
}
if target.Flen < 64 && uintValue >= 1<<(uint64(target.Flen)) {
return Datum{}, errors.Trace(ErrOverflow.GenWithStackByArgs("BIT", fmt.Sprintf("(%d)", target.Flen)))
return Datum{}, errors.Trace(ErrDataTooLong.GenWithStack("Data Too Long, field len %d", target.Flen))
}
byteSize := (target.Flen + 7) >> 3
ret.SetMysqlBit(NewBinaryLiteralFromUint(uintValue, byteSize))
Expand Down

0 comments on commit b736230

Please sign in to comment.