Skip to content

Commit

Permalink
cherry pick pingcap#17635 to release-4.0
Browse files Browse the repository at this point in the history
Signed-off-by: sre-bot <sre-bot@pingcap.com>
  • Loading branch information
wjhuang2016 authored and sre-bot committed Jun 5, 2020
1 parent 9fd3001 commit 89ea138
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 19 deletions.
2 changes: 1 addition & 1 deletion ddl/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2370,7 +2370,7 @@ func (s *testDBSuite2) TestCreateTableWithSetCol(c *C) {
" `b` set('e') DEFAULT ''\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"))
s.tk.MustExec("drop table t_set")
s.tk.MustExec("create table t_set (a set('a', 'b', 'c', 'd') default 'a,C,c');")
s.tk.MustExec("create table t_set (a set('a', 'b', 'c', 'd') default 'a,c,c');")
s.tk.MustQuery("show create table t_set").Check(testkit.Rows("t_set CREATE TABLE `t_set` (\n" +
" `a` set('a','b','c','d') DEFAULT 'a,c'\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"))
Expand Down
2 changes: 1 addition & 1 deletion ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ func setSetDefaultValue(v types.Datum, col *table.Column) (string, error) {
if existCnt != len(valMap) {
return "", ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O)
}
setVal, err := types.ParseSetName(col.Elems, str)
setVal, err := types.ParseSetName(col.Elems, str, col.Collate)
if err != nil {
return "", ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O)
}
Expand Down
8 changes: 4 additions & 4 deletions executor/aggfuncs/func_first_row_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ import (

func (s *testSuite) TestMergePartialResult4FirstRow(c *C) {
elems := []string{"a", "b", "c", "d", "e"}
enumA, _ := types.ParseEnumName(elems, "a")
enumC, _ := types.ParseEnumName(elems, "c")
enumA, _ := types.ParseEnumName(elems, "a", mysql.DefaultCollationName)
enumC, _ := types.ParseEnumName(elems, "c", mysql.DefaultCollationName)

setA, _ := types.ParseSetName(elems, "a")
setAB, _ := types.ParseSetName(elems, "a,b")
setA, _ := types.ParseSetName(elems, "a", mysql.DefaultCollationName)
setAB, _ := types.ParseSetName(elems, "a,b", mysql.DefaultCollationName)

tests := []aggTest{
buildAggTester(ast.AggFuncFirstRow, mysql.TypeLonglong, 5, 0, 2, 0),
Expand Down
4 changes: 2 additions & 2 deletions types/datum.go
Original file line number Diff line number Diff line change
Expand Up @@ -1346,7 +1346,7 @@ func (d *Datum) convertToMysqlEnum(sc *stmtctx.StatementContext, target *FieldTy
)
switch d.k {
case KindString, KindBytes:
e, err = ParseEnumName(target.Elems, d.GetString())
e, err = ParseEnumName(target.Elems, d.GetString(), target.Collate)
default:
var uintDatum Datum
uintDatum, err = d.convertToUint(sc, target)
Expand All @@ -1371,7 +1371,7 @@ func (d *Datum) convertToMysqlSet(sc *stmtctx.StatementContext, target *FieldTyp
)
switch d.k {
case KindString, KindBytes:
s, err = ParseSetName(target.Elems, d.GetString())
s, err = ParseSetName(target.Elems, d.GetString(), target.Collate)
default:
var uintDatum Datum
uintDatum, err = d.convertToUint(sc, target)
Expand Down
7 changes: 4 additions & 3 deletions types/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ package types

import (
"strconv"
"strings"

"github.com/pingcap/errors"
"github.com/pingcap/tidb/util/collate"
"github.com/pingcap/tidb/util/stringutil"
)

Expand Down Expand Up @@ -46,9 +46,10 @@ func (e Enum) ToNumber() float64 {
}

// ParseEnumName creates a Enum with item name.
func ParseEnumName(elems []string, name string) (Enum, error) {
func ParseEnumName(elems []string, name string, collation string) (Enum, error) {
ctor := collate.GetCollator(collation)
for i, n := range elems {
if strings.EqualFold(n, name) {
if ctor.Compare(n, name) == 0 {
return Enum{Name: n, Value: uint64(i) + 1}, nil
}
}
Expand Down
32 changes: 30 additions & 2 deletions types/enum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@ package types

import (
. "github.com/pingcap/check"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/tidb/util/collate"
"github.com/pingcap/tidb/util/testleak"
)

var _ = Suite(&testEnumSuite{})
var _ = SerialSuites(&testEnumSuite{})

type testEnumSuite struct {
}

func (s *testEnumSuite) TestEnum(c *C) {
defer testleak.AfterTest(c)()
collate.SetNewCollationEnabledForTest(true)
defer collate.SetNewCollationEnabledForTest(false)
tbl := []struct {
Elems []string
Name string
Expand All @@ -34,9 +38,33 @@ func (s *testEnumSuite) TestEnum(c *C) {
{[]string{"a"}, "b", 0},
{[]string{"a"}, "1", 1},
}
citbl := []struct {
Elems []string
Name string
Expected int
}{
{[]string{"a", "b"}, "A ", 1},
{[]string{"a"}, "A", 1},
{[]string{"a"}, "b", 0},
{[]string{"啊"}, "啊", 1},
{[]string{"a"}, "1", 1},
}

for _, t := range tbl {
e, err := ParseEnumName(t.Elems, t.Name)
e, err := ParseEnumName(t.Elems, t.Name, mysql.DefaultCollationName)
if t.Expected == 0 {
c.Assert(err, NotNil)
c.Assert(e.ToNumber(), Equals, float64(0))
c.Assert(e.String(), Equals, "")
continue
}

c.Assert(err, IsNil)
c.Assert(e.String(), Equals, t.Elems[t.Expected-1])
c.Assert(e.ToNumber(), Equals, float64(t.Expected))
}
for _, t := range citbl {
e, err := ParseEnumName(t.Elems, t.Name, "utf8_general_ci")
if t.Expected == 0 {
c.Assert(err, NotNil)
c.Assert(e.ToNumber(), Equals, float64(0))
Expand Down
9 changes: 6 additions & 3 deletions types/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"strings"

"github.com/pingcap/errors"
"github.com/pingcap/tidb/util/collate"
"github.com/pingcap/tidb/util/stringutil"
)

Expand Down Expand Up @@ -48,21 +49,23 @@ func (e Set) Copy() Set {
}

// ParseSetName creates a Set with name.
func ParseSetName(elems []string, name string) (Set, error) {
func ParseSetName(elems []string, name string, collation string) (Set, error) {
if len(name) == 0 {
return zeroSet, nil
}

ctor := collate.GetCollator(collation)

seps := strings.Split(name, ",")
marked := make(map[string]struct{}, len(seps))
for _, s := range seps {
marked[strings.ToLower(s)] = struct{}{}
marked[string(ctor.Key(s))] = struct{}{}
}
items := make([]string, 0, len(seps))

value := uint64(0)
for i, n := range elems {
key := strings.ToLower(n)
key := string(ctor.Key(n))
if _, ok := marked[key]; ok {
value |= 1 << uint64(i)
delete(marked, key)
Expand Down
24 changes: 21 additions & 3 deletions types/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@ package types

import (
. "github.com/pingcap/check"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/tidb/util/collate"
"github.com/pingcap/tidb/util/testleak"
)

var _ = Suite(&testSetSuite{})
var _ = SerialSuites(&testSetSuite{})

type testSetSuite struct {
}

func (s *testSetSuite) TestSet(c *C) {
defer testleak.AfterTest(c)()
collate.SetNewCollationEnabledForTest(true)
defer collate.SetNewCollationEnabledForTest(false)
elems := []string{"a", "b", "c", "d"}
tbl := []struct {
Name string
Expand All @@ -39,9 +43,23 @@ func (s *testSetSuite) TestSet(c *C) {
{"", 0, ""},
{"0", 0, ""},
}
citbl := []struct {
Name string
ExpectedValue uint64
ExpectedName string
}{
{"A ", 1, "a"},
{"a,B,a", 3, "a,b"},
}

for _, t := range tbl {
e, err := ParseSetName(elems, t.Name)
e, err := ParseSetName(elems, t.Name, mysql.DefaultCollationName)
c.Assert(err, IsNil)
c.Assert(e.ToNumber(), Equals, float64(t.ExpectedValue))
c.Assert(e.String(), Equals, t.ExpectedName)
}
for _, t := range citbl {
e, err := ParseSetName(elems, t.Name, "utf8_general_ci")
c.Assert(err, IsNil)
c.Assert(e.ToNumber(), Equals, float64(t.ExpectedValue))
c.Assert(e.String(), Equals, t.ExpectedName)
Expand Down Expand Up @@ -69,7 +87,7 @@ func (s *testSetSuite) TestSet(c *C) {
"e.f",
}
for _, t := range tblErr {
_, err := ParseSetName(elems, t)
_, err := ParseSetName(elems, t, mysql.DefaultCollationName)
c.Assert(err, NotNil)
}

Expand Down

0 comments on commit 89ea138

Please sign in to comment.