diff --git a/executor/insert_test.go b/executor/insert_test.go index 1ad3ab5dae696..0ec561cb04a40 100644 --- a/executor/insert_test.go +++ b/executor/insert_test.go @@ -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" ) @@ -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.*") + +} diff --git a/types/datum.go b/types/datum.go index 0d2053f06e954..7118531652c40 100644 --- a/types/datum.go +++ b/types/datum.go @@ -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))