Skip to content

Commit

Permalink
use @@session.collation_server during create database ... (#2426)
Browse files Browse the repository at this point in the history
  • Loading branch information
jycor committed Apr 2, 2024
1 parent a7c3dd0 commit 5a671f6
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 26 deletions.
112 changes: 112 additions & 0 deletions enginetest/queries/charset_collation_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,118 @@ var CharsetCollationEngineTests = []CharsetCollationEngineTest{
},
},
},
{
Name: "setting charset/collation sets the other",
Queries: []CharsetCollationEngineTestQuery{
{
Query: "select @@session.character_set_connection, @@session.collation_connection;",
Expected: []sql.Row{
{"utf8mb4", "utf8mb4_0900_bin"},
},
},
{
Query: "set @@session.character_set_connection = 'latin1';",
Expected: []sql.Row{{}},
},
{
Query: "select @@session.character_set_connection, @@session.collation_connection;",
Expected: []sql.Row{
{"latin1", "latin1_swedish_ci"},
},
},
{
Query: "set @@session.collation_connection = 'utf8mb4_0900_bin';",
Expected: []sql.Row{{}},
},
{
Query: "select @@session.character_set_connection, @@session.collation_connection;",
Expected: []sql.Row{
{"utf8mb4", "utf8mb4_0900_bin"},
},
},

{
Query: "select @@global.character_set_connection, @@global.collation_connection;",
Expected: []sql.Row{
{"utf8mb4", "utf8mb4_0900_bin"},
},
},
{
Query: "set @@global.character_set_connection = 'latin1';",
Expected: []sql.Row{{}},
},
{
Query: "select @@global.character_set_connection, @@global.collation_connection;",
Expected: []sql.Row{
{"latin1", "latin1_swedish_ci"},
},
},
{
Query: "set @@global.collation_connection = 'utf8mb4_0900_bin';",
Expected: []sql.Row{{}},
},
{
Query: "select @@global.character_set_connection, @@global.collation_connection;",
Expected: []sql.Row{
{"utf8mb4", "utf8mb4_0900_bin"},
},
},

{
Query: "select @@session.character_set_server, @@session.collation_server;",
Expected: []sql.Row{
{"utf8mb4", "utf8mb4_0900_bin"},
},
},
{
Query: "set @@session.character_set_server = 'latin1';",
Expected: []sql.Row{{}},
},
{
Query: "select @@session.character_set_server, @@session.collation_server;",
Expected: []sql.Row{
{"latin1", "latin1_swedish_ci"},
},
},
{
Query: "set @@session.collation_server = 'utf8mb4_0900_bin';",
Expected: []sql.Row{{}},
},
{
Query: "select @@session.character_set_server, @@session.collation_server;",
Expected: []sql.Row{
{"utf8mb4", "utf8mb4_0900_bin"},
},
},

{
Query: "select @@global.character_set_server, @@global.collation_server;",
Expected: []sql.Row{
{"utf8mb4", "utf8mb4_0900_bin"},
},
},
{
Query: "set @@global.character_set_server = 'latin1';",
Expected: []sql.Row{{}},
},
{
Query: "select @@global.character_set_server, @@global.collation_server;",
Expected: []sql.Row{
{"latin1", "latin1_swedish_ci"},
},
},
{
Query: "set @@global.collation_server = 'utf8mb4_0900_bin';",
Expected: []sql.Row{{}},
},
{
Query: "select @@global.character_set_server, @@global.collation_server;",
Expected: []sql.Row{
{"utf8mb4", "utf8mb4_0900_bin"},
},
},
},
},
{
Name: "ENUM collation handling",
SetUpScript: []string{
Expand Down
28 changes: 28 additions & 0 deletions enginetest/queries/script_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -6302,6 +6302,34 @@ where
},
},
},
{
Name: "test create database with modified server variables",
SetUpScript: []string{
"set @@session.character_set_server = 'latin1';",
"create database latin1_db;",
},
Assertions: []ScriptTestAssertion{
{
Query: "select @@global.character_set_server, @@global.collation_server;",
Expected: []sql.Row{
{"utf8mb4", "utf8mb4_0900_bin"},
},
},
{
Query: "select @@session.character_set_server, @@session.collation_server;",
Expected: []sql.Row{
{"latin1", "latin1_swedish_ci"},
},
},
{
// Interestingly, session actually takes priority over global
Query: "show create database latin1_db",
Expected: []sql.Row{
{"latin1_db", "CREATE DATABASE `latin1_db` /*!40100 DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci */"},
},
},
},
},
}

var SpatialScriptTests = []ScriptTest{
Expand Down
8 changes: 8 additions & 0 deletions sql/planbuilder/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,14 @@ func (b *Builder) buildDBDDL(inScope *scope, c *ast.DBDDL) (outScope *scope) {
collationStr = cc.Value
}
}
// TODO: ensure that collation and charset match when setting them
if len(charsetStr) == 0 && len(collationStr) == 0 {
collation, err := b.ctx.Session.GetSessionVariable(b.ctx, "collation_server")
if err != nil {
b.handleErr(err)
}
collationStr = collation.(string)
}
collation, err := sql.ParseCollation(charsetStr, collationStr, false)
if err != nil {
b.handleErr(err)
Expand Down
85 changes: 61 additions & 24 deletions sql/rowexec/rel_iters.go
Original file line number Diff line number Diff line change
Expand Up @@ -633,33 +633,70 @@ func setSystemVar(ctx *sql.Context, sysVar *expression.SystemVar, right sql.Expr
if err != nil {
return err
}
// Setting `character_set_connection`, regardless of how it is set (directly or through SET NAMES) will also set
// `collation_connection` to the default collation for the given character set.
if strings.ToLower(sysVar.Name) == "character_set_connection" {
newSysVar := &expression.SystemVar{
Name: "collation_connection",
Scope: sysVar.Scope,

// Setting `character_set_connection` and `collation_connection` will set the corresponding variable
// Setting `character_set_server` and `collation_server` will set the corresponding variable
switch strings.ToLower(sysVar.Name) {
case "character_set_connection":
if val == nil {
return sysVar.Scope.SetValue(ctx, "collation_connection", val)
}
valStr, ok := val.(string)
if !ok {
return sql.ErrInvalidSystemVariableValue.New("collation_connection", val)
}
var charset sql.CharacterSetID
charset, err = sql.ParseCharacterSet(valStr)
if err != nil {
return err
}
collationName := charset.DefaultCollation().Name()
return sysVar.Scope.SetValue(ctx, "collation_connection", collationName)
case "collation_connection":
if val == nil {
err = setSystemVar(ctx, newSysVar, expression.NewLiteral("", types.LongText), row)
if err != nil {
return err
}
} else {
valStr, ok := val.(string)
if !ok {
return sql.ErrInvalidSystemVariableValue.New("collation_connection", val)
}
charset, err := sql.ParseCharacterSet(valStr)
if err != nil {
return err
}
charset = charset
err = setSystemVar(ctx, newSysVar, expression.NewLiteral(charset.DefaultCollation().Name(), types.LongText), row)
if err != nil {
return err
}
return sysVar.Scope.SetValue(ctx, "character_set_connection", val)
}
valStr, ok := val.(string)
if !ok {
return sql.ErrInvalidSystemVariableValue.New("character_set_connection", val)
}
var collation sql.CollationID
collation, err = sql.ParseCollation("", valStr, false)
if err != nil {
return err
}
charsetName := collation.CharacterSet().Name()
return sysVar.Scope.SetValue(ctx, "character_set_connection", charsetName)
case "character_set_server":
if val == nil {
return sysVar.Scope.SetValue(ctx, "collation_server", val)
}
valStr, ok := val.(string)
if !ok {
return sql.ErrInvalidSystemVariableValue.New("collation_server", val)
}
var charset sql.CharacterSetID
charset, err = sql.ParseCharacterSet(valStr)
if err != nil {
return err
}
collationName := charset.DefaultCollation().Name()
return sysVar.Scope.SetValue(ctx, "collation_server", collationName)
case "collation_server":
if val == nil {
return sysVar.Scope.SetValue(ctx, "character_set_server", val)
}
valStr, ok := val.(string)
if !ok {
return sql.ErrInvalidSystemVariableValue.New("character_set_server", val)
}
var collation sql.CollationID
collation, err = sql.ParseCollation("", valStr, false)
if err != nil {
return err
}
charsetName := collation.CharacterSet().Name()
return sysVar.Scope.SetValue(ctx, "character_set_server", charsetName)
}
return nil
}
Expand Down
5 changes: 3 additions & 2 deletions sql/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ const (
)

const (
CurrentDBSessionVar = "current_database"
AutoCommitSessionVar = "autocommit"
CurrentDBSessionVar = "current_database"
AutoCommitSessionVar = "autocommit"
// TODO: how does character set and collation get matched?
characterSetConnectionSysVarName = "character_set_connection"
characterSetResultsSysVarName = "character_set_results"
collationConnectionSysVarName = "collation_connection"
Expand Down

0 comments on commit 5a671f6

Please sign in to comment.