From 5d0e1cdccbe44b8a9006655903cb10cbb2955080 Mon Sep 17 00:00:00 2001 From: Yang Keao Date: Mon, 11 Nov 2024 22:05:07 +0800 Subject: [PATCH] fix the issue that the default value for BIT is wrong Signed-off-by: Yang Keao --- pkg/ddl/add_column.go | 15 +++++++++++++++ pkg/table/column.go | 6 ++++++ tests/integrationtest/r/ddl/column.result | 10 ++++++++++ tests/integrationtest/r/table/tables.result | 6 ++++++ tests/integrationtest/t/ddl/column.test | 12 ++++++++++++ tests/integrationtest/t/table/tables.test | 6 ++++++ 6 files changed, 55 insertions(+) diff --git a/pkg/ddl/add_column.go b/pkg/ddl/add_column.go index e9cdb4296c4de..72dc70a941294 100644 --- a/pkg/ddl/add_column.go +++ b/pkg/ddl/add_column.go @@ -1225,6 +1225,21 @@ func checkColumnDefaultValue(ctx exprctx.BuildContext, col *table.Column, value } } } + if value != nil && col.GetType() == mysql.TypeBit { + v, ok := value.(string) + if !ok { + return hasDefaultValue, value, types.ErrInvalidDefault.GenWithStackByArgs(col.Name.O) + } + + // FIXME: the length of the original bit literal has been lost and it'll be ceiled to bytes. + // For example, the following DDL will be allowed, because 4 = 32 / 8. + // CREATE TABLE t (a bit(25) default b'111111111111111111111111111111'); + // + // The `Flen` is ceiled to make sure the DDL allowed in MySQL is also allowed in TiDB. + if (col.GetFlen()+7)/8 < len(v) { + return hasDefaultValue, value, types.ErrInvalidDefault.GenWithStackByArgs(col.Name.O) + } + } return hasDefaultValue, value, nil } diff --git a/pkg/table/column.go b/pkg/table/column.go index 4b20df2cab7ee..de6740acd4c23 100644 --- a/pkg/table/column.go +++ b/pkg/table/column.go @@ -614,6 +614,12 @@ func getColDefaultValue(ctx expression.BuildContext, col *model.ColumnInfo, defa switch col.GetType() { case mysql.TypeTimestamp, mysql.TypeDate, mysql.TypeDatetime: + case mysql.TypeBit: + defaultValBytes, ok := defaultVal.(string) + intest.Assert(ok, "the default value type for bit should be string") + if ok { + return types.NewBinaryLiteralDatum(types.BinaryLiteral(defaultValBytes)), nil + } default: value, err := CastColumnValue(ctx, types.NewDatum(defaultVal), col, false, false) if err != nil { diff --git a/tests/integrationtest/r/ddl/column.result b/tests/integrationtest/r/ddl/column.result index 8ca8082543310..3eda0de2787a9 100644 --- a/tests/integrationtest/r/ddl/column.result +++ b/tests/integrationtest/r/ddl/column.result @@ -84,3 +84,13 @@ t CREATE TABLE `t` ( `a` decimal(10,0) DEFAULT NULL, `b` decimal(10,0) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin +drop table if exists t; +create table t(a bit(2) default b'1111111111111111111111111111111'); +Error 1067 (42000): Invalid default value for 'a' +create table t(a bit(4) default b'1111111111111111111111111111111'); +Error 1067 (42000): Invalid default value for 'a' +create table t(a bit(24) default b'111111111111111111111111111111'); +Error 1067 (42000): Invalid default value for 'a' +create table t(a bit(25) default b'111111111111111111111111111111'); -- fix me. TiDB cannot know the accurate bit literal length after parser, so the 25 bits limitation are ceiled to 32. +drop table t; +create table t(a bit(32) default b'1111111111111111111111111111111'); diff --git a/tests/integrationtest/r/table/tables.result b/tests/integrationtest/r/table/tables.result index 9f52a2e817c42..ada09d0f5d006 100644 --- a/tests/integrationtest/r/table/tables.result +++ b/tests/integrationtest/r/table/tables.result @@ -24,3 +24,9 @@ select count(distinct(_tidb_rowid>>48)) from shard_t; count(distinct(_tidb_rowid>>48)) 3 set @@tidb_shard_allocate_step=default; +drop table if exists t; +create table t(a bit(32) default b'1100010001001110011000100100111'); +insert into t values (); +select hex(a) from t; +hex(a) +62273127 diff --git a/tests/integrationtest/t/ddl/column.test b/tests/integrationtest/t/ddl/column.test index e92fd4f0371a0..45611b15d7ecc 100644 --- a/tests/integrationtest/t/ddl/column.test +++ b/tests/integrationtest/t/ddl/column.test @@ -44,3 +44,15 @@ alter table t1 add column d date default '2024-10'; drop table if exists t; create table t(a decimal(0,0), b decimal(0)); show create table t; + +# TestTooLongDefaultValueForBit +drop table if exists t; +-- error 1067 +create table t(a bit(2) default b'1111111111111111111111111111111'); +-- error 1067 +create table t(a bit(4) default b'1111111111111111111111111111111'); +-- error 1067 +create table t(a bit(24) default b'111111111111111111111111111111'); +create table t(a bit(25) default b'111111111111111111111111111111'); -- fix me. TiDB cannot know the accurate bit literal length after parser, so the 25 bits limitation are ceiled to 32. +drop table t; +create table t(a bit(32) default b'1111111111111111111111111111111'); \ No newline at end of file diff --git a/tests/integrationtest/t/table/tables.test b/tests/integrationtest/t/table/tables.test index e963a7a1ce073..9446a5b0921a0 100644 --- a/tests/integrationtest/t/table/tables.test +++ b/tests/integrationtest/t/table/tables.test @@ -22,3 +22,9 @@ insert into shard_t values (12); select count(distinct(_tidb_rowid>>48)) from shard_t; set @@tidb_shard_allocate_step=default; + +# TestInsertBitDefaultValue +drop table if exists t; +create table t(a bit(32) default b'1100010001001110011000100100111'); +insert into t values (); +select hex(a) from t; \ No newline at end of file