Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 13 additions & 24 deletions pkg/executor/test/ddl/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,31 +118,20 @@ func TestCreateTable(t *testing.T) {

// test multiple collate specified in column when create.
tk.MustExec("drop table if exists test_multiple_column_collate;")
tk.MustExec("create table test_multiple_column_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin")
tt, err := domain.GetDomain(tk.Session()).InfoSchema().TableByName(context.Background(), ast.NewCIStr("test"), ast.NewCIStr("test_multiple_column_collate"))
require.NoError(t, err)
require.Equal(t, "utf8", tt.Cols()[0].GetCharset())
require.Equal(t, "utf8_general_ci", tt.Cols()[0].GetCollate())
require.Equal(t, "utf8mb4", tt.Meta().Charset)
require.Equal(t, "utf8mb4_bin", tt.Meta().Collate)
tk.MustContainErrMsg("create table test_multiple_column_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin",
"Multiple COLLATE clauses")

tk.MustExec("drop table if exists test_multiple_column_collate;")
tk.MustExec("create table test_multiple_column_collate (a char(1) charset utf8 collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin")
tt, err = domain.GetDomain(tk.Session()).InfoSchema().TableByName(context.Background(), ast.NewCIStr("test"), ast.NewCIStr("test_multiple_column_collate"))
require.NoError(t, err)
require.Equal(t, "utf8", tt.Cols()[0].GetCharset())
require.Equal(t, "utf8_general_ci", tt.Cols()[0].GetCollate())
require.Equal(t, "utf8mb4", tt.Meta().Charset)
require.Equal(t, "utf8mb4_bin", tt.Meta().Collate)
tk.MustContainErrMsg("create table test_multiple_column_collate (a char(1) charset utf8 collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin",
"Multiple COLLATE clauses")

// test Err case for multiple collate specified in column when create.
tk.MustExec("drop table if exists test_err_multiple_collate;")
tk.MustGetErrMsg("create table test_err_multiple_collate (a char(1) charset utf8mb4 collate utf8_unicode_ci collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin",
dbterror.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8_unicode_ci", "utf8mb4").Error())
tk.MustContainErrMsg("create table test_err_multiple_collate (a char(1) charset utf8mb4 collate utf8_unicode_ci collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin",
"Multiple COLLATE clauses")

tk.MustExec("drop table if exists test_err_multiple_collate;")
tk.MustGetErrMsg("create table test_err_multiple_collate (a char(1) collate utf8_unicode_ci collate utf8mb4_general_ci) charset utf8mb4 collate utf8mb4_bin",
dbterror.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8mb4_general_ci", "utf8").Error())
tk.MustContainErrMsg("create table test_err_multiple_collate (a char(1) collate utf8_unicode_ci collate utf8mb4_general_ci) charset utf8mb4 collate utf8mb4_bin",
"Multiple COLLATE clauses")

// table option is auto-increment
tk.MustExec("drop table if exists create_auto_increment_test;")
Expand Down Expand Up @@ -356,7 +345,7 @@ func TestAlterTableModifyColumn(t *testing.T) {

// test multiple collate modification in column.
tk.MustExec("drop table if exists modify_column_multiple_collate")
tk.MustExec("create table modify_column_multiple_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin")
tk.MustExec("create table modify_column_multiple_collate (a char(1) collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin")
tk.MustExec("alter table modify_column_multiple_collate modify column a char(1) collate utf8mb4_bin;")
tt, err := domain.GetDomain(tk.Session()).InfoSchema().TableByName(context.Background(), ast.NewCIStr("test"), ast.NewCIStr("modify_column_multiple_collate"))
require.NoError(t, err)
Expand All @@ -366,7 +355,7 @@ func TestAlterTableModifyColumn(t *testing.T) {
require.Equal(t, "utf8mb4_bin", tt.Meta().Collate)

tk.MustExec("drop table if exists modify_column_multiple_collate;")
tk.MustExec("create table modify_column_multiple_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin")
tk.MustExec("create table modify_column_multiple_collate (a char(1) collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin")
tk.MustExec("alter table modify_column_multiple_collate modify column a char(1) charset utf8mb4 collate utf8mb4_bin;")
tt, err = domain.GetDomain(tk.Session()).InfoSchema().TableByName(context.Background(), ast.NewCIStr("test"), ast.NewCIStr("modify_column_multiple_collate"))
require.NoError(t, err)
Expand All @@ -377,12 +366,12 @@ func TestAlterTableModifyColumn(t *testing.T) {

// test Err case for multiple collate modification in column.
tk.MustExec("drop table if exists err_modify_multiple_collate;")
tk.MustExec("create table err_modify_multiple_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin")
tk.MustExec("create table err_modify_multiple_collate (a char(1) collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin")
tk.MustGetErrMsg("alter table err_modify_multiple_collate modify column a char(1) charset utf8mb4 collate utf8_bin;", dbterror.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8_bin", "utf8mb4").Error())

tk.MustExec("drop table if exists err_modify_multiple_collate;")
tk.MustExec("create table err_modify_multiple_collate (a char(1) collate utf8_bin collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin")
tk.MustGetErrMsg("alter table err_modify_multiple_collate modify column a char(1) collate utf8_bin collate utf8mb4_bin;", dbterror.ErrCollationCharsetMismatch.GenWithStackByArgs("utf8mb4_bin", "utf8").Error())
tk.MustExec("create table err_modify_multiple_collate (a char(1) collate utf8_general_ci) charset utf8mb4 collate utf8mb4_bin")
tk.MustContainErrMsg("alter table err_modify_multiple_collate modify column a char(1) collate utf8_bin collate utf8mb4_bin;", "Multiple COLLATE clauses")
}

func TestColumnCharsetAndCollate(t *testing.T) {
Expand Down
6 changes: 6 additions & 0 deletions pkg/parser/ast/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,12 @@ var (
}
)

// ColumnOptionList stores column options.
type ColumnOptionList struct {
HasCollateOption bool
Options []*ColumnOption
}

// ColumnOption is used for parsing column constraint info from SQL.
type ColumnOption struct {
node
Expand Down
2 changes: 0 additions & 2 deletions pkg/parser/ast/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ func TestDDLColumnDefRestore(t *testing.T) {
{"id text charset UTF8", "`id` TEXT CHARACTER SET UTF8"},
{"id varchar(50) collate UTF8MB4_CZECH_CI", "`id` VARCHAR(50) COLLATE utf8mb4_czech_ci"},
{"id varchar(50) collate utf8_bin", "`id` VARCHAR(50) COLLATE utf8_bin"},
{"id varchar(50) collate utf8_unicode_ci collate utf8mb4_bin", "`id` VARCHAR(50) COLLATE utf8_unicode_ci COLLATE utf8mb4_bin"},
{"c1 char(10) character set LATIN1 collate latin1_german1_ci", "`c1` CHAR(10) CHARACTER SET LATIN1 COLLATE latin1_german1_ci"},

{"id int(11) PRIMARY KEY", "`id` INT(11) PRIMARY KEY"},
Expand All @@ -320,7 +319,6 @@ func TestDDLColumnDefRestore(t *testing.T) {
{"id INT(11) DEFAULT 1.1", "`id` INT(11) DEFAULT 1.1"},
{"id INT(11) UNIQUE KEY", "`id` INT(11) UNIQUE KEY"},
{"id INT(11) COLLATE ascii_bin", "`id` INT(11) COLLATE ascii_bin"},
{"id INT(11) collate ascii_bin collate utf8_bin", "`id` INT(11) COLLATE ascii_bin COLLATE utf8_bin"},
{"id INT(11) on update CURRENT_TIMESTAMP", "`id` INT(11) ON UPDATE CURRENT_TIMESTAMP()"},
{"id INT(11) comment 'hello'", "`id` INT(11) COMMENT 'hello'"},
{"id INT(11) generated always as(id + 1)", "`id` INT(11) GENERATED ALWAYS AS(`id`+1) VIRTUAL"},
Expand Down
37 changes: 29 additions & 8 deletions pkg/parser/parser.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 29 additions & 8 deletions pkg/parser/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -3451,7 +3451,7 @@ BinlogStmt:
ColumnDef:
ColumnName Type ColumnOptionListOpt
{
colDef := &ast.ColumnDef{Name: $1.(*ast.ColumnName), Tp: $2.(*types.FieldType), Options: $3.([]*ast.ColumnOption)}
colDef := &ast.ColumnDef{Name: $1.(*ast.ColumnName), Tp: $2.(*types.FieldType), Options: $3.(ast.ColumnOptionList).Options}
if err := colDef.Validate(); err != nil {
yylex.AppendError(err)
return 1
Expand All @@ -3463,7 +3463,7 @@ ColumnDef:
// TODO: check flen 0
tp := types.NewFieldType(mysql.TypeLonglong)
options := []*ast.ColumnOption{{Tp: ast.ColumnOptionNotNull}, {Tp: ast.ColumnOptionAutoIncrement}, {Tp: ast.ColumnOptionUniqKey}}
options = append(options, $3.([]*ast.ColumnOption)...)
options = append(options, $3.(ast.ColumnOptionList).Options...)
tp.AddFlag(mysql.UnsignedFlag)
colDef := &ast.ColumnDef{Name: $1.(*ast.ColumnName), Tp: tp, Options: options}
if err := colDef.Validate(); err != nil {
Expand Down Expand Up @@ -3665,7 +3665,9 @@ ColumnOption:
}
| "SERIAL" "DEFAULT" "VALUE"
{
$$ = []*ast.ColumnOption{{Tp: ast.ColumnOptionNotNull}, {Tp: ast.ColumnOptionAutoIncrement}, {Tp: ast.ColumnOptionUniqKey}}
$$ = ast.ColumnOptionList{
Options: []*ast.ColumnOption{{Tp: ast.ColumnOptionNotNull}, {Tp: ast.ColumnOptionAutoIncrement}, {Tp: ast.ColumnOptionUniqKey}},
}
}
| "ON" "UPDATE" NowSymOptionFraction
{
Expand All @@ -3692,7 +3694,9 @@ ColumnOption:
}
switch $6.(int) {
case 0:
$$ = []*ast.ColumnOption{optionCheck, {Tp: ast.ColumnOptionNotNull}}
$$ = ast.ColumnOptionList{
Options: []*ast.ColumnOption{optionCheck, {Tp: ast.ColumnOptionNotNull}},
}
case 1:
optionCheck.Enforced = true
$$ = optionCheck
Expand Down Expand Up @@ -3794,23 +3798,40 @@ ColumnOptionList:
ColumnOption
{
if columnOption, ok := $1.(*ast.ColumnOption); ok {
$$ = []*ast.ColumnOption{columnOption}
hasCollateOption := false
if columnOption.Tp == ast.ColumnOptionCollate {
hasCollateOption = true
}
$$ = ast.ColumnOptionList{
HasCollateOption: hasCollateOption,
Options: []*ast.ColumnOption{columnOption},
}
} else {
$$ = $1
}
}
| ColumnOptionList ColumnOption
{
columnOptionList := $1.(ast.ColumnOptionList)
if columnOption, ok := $2.(*ast.ColumnOption); ok {
$$ = append($1.([]*ast.ColumnOption), columnOption)
if columnOption.Tp == ast.ColumnOptionCollate && columnOptionList.HasCollateOption {
yylex.AppendError(ErrParse.GenWithStackByArgs("Multiple COLLATE clauses", yylex.Errorf("").Error()))
return 1
}
columnOptionList.Options = append(columnOptionList.Options, columnOption)
} else {
$$ = append($1.([]*ast.ColumnOption), $2.([]*ast.ColumnOption)...)
if columnOptionList.HasCollateOption && $2.(ast.ColumnOptionList).HasCollateOption {
yylex.AppendError(ErrParse.GenWithStackByArgs("Multiple COLLATE clauses", yylex.Errorf("").Error()))
return 1
}
columnOptionList.Options = append(columnOptionList.Options, $2.(ast.ColumnOptionList).Options...)
}
$$ = columnOptionList
}

ColumnOptionListOpt:
{
$$ = []*ast.ColumnOption{}
$$ = ast.ColumnOptionList{}
}
| ColumnOptionList

Expand Down
10 changes: 5 additions & 5 deletions pkg/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2511,14 +2511,14 @@ func TestDDL(t *testing.T) {
{"CREATE TABLE foo (name CHAR(50) CHARACTER SET utf8 BINARY)", true, "CREATE TABLE `foo` (`name` CHAR(50) BINARY CHARACTER SET UTF8)"},
{"CREATE TABLE foo (name CHAR(50) CHARACTER SET utf8 BINARY CHARACTER set utf8)", false, ""},
{"CREATE TABLE foo (name CHAR(50) BINARY CHARACTER SET utf8 COLLATE utf8_bin)", true, "CREATE TABLE `foo` (`name` CHAR(50) BINARY CHARACTER SET UTF8 COLLATE utf8_bin)"},
{"CREATE TABLE foo (name CHAR(50) CHARACTER SET utf8 COLLATE utf8_bin COLLATE ascii_bin)", true, "CREATE TABLE `foo` (`name` CHAR(50) CHARACTER SET UTF8 COLLATE utf8_bin COLLATE ascii_bin)"},
{"CREATE TABLE foo (name CHAR(50) COLLATE ascii_bin COLLATE latin1_bin)", true, "CREATE TABLE `foo` (`name` CHAR(50) COLLATE ascii_bin COLLATE latin1_bin)"},
{"CREATE TABLE foo (name CHAR(50) COLLATE ascii_bin PRIMARY KEY COLLATE latin1_bin)", true, "CREATE TABLE `foo` (`name` CHAR(50) COLLATE ascii_bin PRIMARY KEY COLLATE latin1_bin)"},
{"CREATE TABLE foo (name CHAR(50) CHARACTER SET utf8 COLLATE utf8_bin COLLATE ascii_bin)", false, ""},
{"CREATE TABLE foo (name CHAR(50) COLLATE ascii_bin COLLATE latin1_bin)", false, ""},
{"CREATE TABLE foo (name CHAR(50) COLLATE ascii_bin PRIMARY KEY COLLATE latin1_bin)", false, ""},
{"CREATE TABLE foo (a.b, b);", false, ""},
{"CREATE TABLE foo (a, b.c);", false, ""},
{"CREATE TABLE (name CHAR(50) BINARY)", false, ""},
{"CREATE TABLE foo (name CHAR(50) COLLATE ascii_bin PRIMARY KEY COLLATE latin1_bin, INDEX (name ASC))", true, "CREATE TABLE `foo` (`name` CHAR(50) COLLATE ascii_bin PRIMARY KEY COLLATE latin1_bin,INDEX(`name`))"},
{"CREATE TABLE foo (name CHAR(50) COLLATE ascii_bin PRIMARY KEY COLLATE latin1_bin, INDEX (name DESC))", true, "CREATE TABLE `foo` (`name` CHAR(50) COLLATE ascii_bin PRIMARY KEY COLLATE latin1_bin,INDEX(`name` DESC))"},
{"CREATE TABLE foo (name CHAR(50) COLLATE ascii_bin PRIMARY KEY COLLATE latin1_bin, INDEX (name ASC))", false, ""},
{"CREATE TABLE foo (name CHAR(50) COLLATE ascii_bin PRIMARY KEY COLLATE latin1_bin, INDEX (name DESC))", false, ""},
// test enable or disable cached table
{"ALTER TABLE tmp CACHE", true, "ALTER TABLE `tmp` CACHE"},
{"ALTER TABLE tmp NOCACHE", true, "ALTER TABLE `tmp` NOCACHE"},
Expand Down