Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

executor: Use charset and collation from server vars for new schemas #27216

Merged
merged 7 commits into from
Oct 19, 2021
52 changes: 47 additions & 5 deletions executor/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/pingcap/tidb/table/temptable"
"github.com/pingcap/tidb/util/admin"
"github.com/pingcap/tidb/util/chunk"
"github.com/pingcap/tidb/util/collate"
"github.com/pingcap/tidb/util/gcutil"
"github.com/pingcap/tidb/util/logutil"
"github.com/pingcap/tidb/util/sqlexec"
Expand Down Expand Up @@ -247,17 +248,36 @@ func (e *DDLExec) executeRenameTable(s *ast.RenameTableStmt) error {
}

func (e *DDLExec) executeCreateDatabase(s *ast.CreateDatabaseStmt) error {
var charOpt *ast.CharsetOpt
var opt *ast.CharsetOpt
var directPlacementOpts *model.PlacementSettings
var placementPolicyRef *model.PolicyRefInfo
var err error
sessionVars := e.ctx.GetSessionVars()

// If no charset and/or collation is specified use collation_server and character_set_server
opt = &ast.CharsetOpt{}
if sessionVars.GlobalVarsAccessor != nil {
opt.Col, err = variable.GetSessionOrGlobalSystemVar(sessionVars, variable.CollationServer)
if err != nil {
return err
}
opt.Chs, err = variable.GetSessionOrGlobalSystemVar(sessionVars, variable.CharacterSetServer)
if err != nil {
return err
}
}

explicitCharset := false
explicitCollation := false
if len(s.Options) != 0 {
charOpt = &ast.CharsetOpt{}
for _, val := range s.Options {
switch val.Tp {
case ast.DatabaseOptionCharset:
charOpt.Chs = val.Value
opt.Chs = val.Value
explicitCharset = true
case ast.DatabaseOptionCollate:
charOpt.Col = val.Value
opt.Col = val.Value
explicitCollation = true
case ast.DatabaseOptionPlacementPrimaryRegion, ast.DatabaseOptionPlacementRegions,
ast.DatabaseOptionPlacementFollowerCount, ast.DatabaseOptionPlacementLeaderConstraints,
ast.DatabaseOptionPlacementLearnerCount, ast.DatabaseOptionPlacementVoterCount,
Expand All @@ -278,7 +298,29 @@ func (e *DDLExec) executeCreateDatabase(s *ast.CreateDatabaseStmt) error {
}
}
}
err := domain.GetDomain(e.ctx).DDL().CreateSchema(e.ctx, model.NewCIStr(s.Name), charOpt, directPlacementOpts, placementPolicyRef)

if opt.Col != "" {
coll, err := collate.GetCollationByName(opt.Col)
if err != nil {
return err
}

// The collation is not valid for the specified character set.
// Try to remove any of them, but not if they are explicitly defined.
if coll.CharsetName != opt.Chs {
if explicitCollation && !explicitCharset {
// Use the explicitly set collation, not the implicit charset.
opt.Chs = ""
}
if !explicitCollation && explicitCharset {
// Use the explicitly set charset, not the (session) collation.
opt.Col = ""
}
}

}

err = domain.GetDomain(e.ctx).DDL().CreateSchema(e.ctx, model.NewCIStr(s.Name), opt, directPlacementOpts, placementPolicyRef)
if err != nil {
if infoschema.ErrDatabaseExists.Equal(err) && s.IfNotExists {
err = nil
Expand Down
21 changes: 21 additions & 0 deletions executor/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,27 @@ func (s *testSuite6) TestCreateDropDatabase(c *C) {
"charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci */",
))
tk.MustGetErrMsg("create database charset_test charset utf8 collate utf8mb4_unicode_ci;", "[ddl:1253]COLLATION 'utf8mb4_unicode_ci' is not valid for CHARACTER SET 'utf8'")

tk.MustExec("SET SESSION character_set_server='ascii'")
tk.MustExec("SET SESSION collation_server='ascii_bin'")

tk.MustExec("drop database charset_test;")
tk.MustExec("create database charset_test;")
tk.MustQuery("show create database charset_test;").Check(testutil.RowsWithSep("|",
"charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET ascii */",
))
dveeden marked this conversation as resolved.
Show resolved Hide resolved

tk.MustExec("drop database charset_test;")
tk.MustExec("create database charset_test collate utf8mb4_general_ci;")
tk.MustQuery("show create database charset_test;").Check(testutil.RowsWithSep("|",
"charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */",
))

tk.MustExec("drop database charset_test;")
tk.MustExec("create database charset_test charset utf8mb4;")
tk.MustQuery("show create database charset_test;").Check(testutil.RowsWithSep("|",
"charset_test|CREATE DATABASE `charset_test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */",
))
}

func (s *testSuite6) TestCreateDropTable(c *C) {
Expand Down