Repository: pingcap/tidb (Go)

Issue:
setting sysvar collation does not normalize 
## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)

```sql
mysql> set global collation_server = 'LaTIN1_bin';
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW GLOBAL VARIABLES LIKE 'collation_server';
+------------------+------------+
| Variable_name    | Value      |
+------------------+------------+
| collation_server | LaTIN1_bin |
+------------------+------------+
1 row in set (0.04 sec)
```

### 2. What did you expect to see? (Required)

The case should be consistently normalized to latin1_bin.

### 3. What did you see instead (Required)

See above.

### 4. What is your TiDB version? (Required)

```sql
mysql> SELECT tidb_version()\G
*************************** 1. row ***************************
tidb_version(): Release Version: v4.0.0-beta.2-2807-g289dcfefd-dirty
Edition: Community
Git Commit Hash: 289dcfefdd159345972f71cf42c9d6e594255290
Git Branch: fix-issue-24414
UTC Build Time: 2021-05-06 15:40:01
GoVersion: go1.13.15
Race Enabled: false
TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306
Check Table Before Drop: false
1 row in set (0.00 sec)
```


Discussion:
## Please edit this comment or add a new comment to complete the following information

### Bug

#### 1. Root Cause Analysis (RCA) (optional) 

Refactoring removed normalization for the collation parameter.

#### 2. Symptom (optional)

<!-- What will the user see when this bug occurs. The error message may be in the terminal, log or monitoring -->

#### 3. All Trigger Conditions (optional)

<!-- All the user scenarios that may trigger this bug -->

#### 4. Workaround (optional)

#### 5. Affected versions

unreleased

#### 6. Fixed versions

master



Patch:
diff --git a/sessionctx/variable/varsutil.go b/sessionctx/variable/varsutil.go
index bb9f0e1841e54..45cebbd62e0db 100644
--- a/sessionctx/variable/varsutil.go
+++ b/sessionctx/variable/varsutil.go
@@ -111,10 +111,11 @@ func int32ToBoolStr(i int32) string {
 }
 
 func checkCollation(vars *SessionVars, normalizedValue string, originalValue string, scope ScopeFlag) (string, error) {
-	if _, err := collate.GetCollationByName(normalizedValue); err != nil {
+	coll, err := collate.GetCollationByName(normalizedValue)
+	if err != nil {
 		return normalizedValue, errors.Trace(err)
 	}
-	return normalizedValue, nil
+	return coll.Name, nil
 }
 
 func checkCharacterSet(normalizedValue string, argName string) (string, error) {


Test patch:
diff --git a/sessionctx/variable/sysvar_test.go b/sessionctx/variable/sysvar_test.go
index 31e44a88ad83f..4029072412977 100644
--- a/sessionctx/variable/sysvar_test.go
+++ b/sessionctx/variable/sysvar_test.go
@@ -15,6 +15,7 @@ package variable
 
 import (
 	"fmt"
+	"strings"
 	"testing"
 
 	. "github.com/pingcap/check"
@@ -227,3 +228,93 @@ func (*testSysVarSuite) TestScope(c *C) {
 	c.Assert(sv.HasSessionScope(), IsFalse)
 	c.Assert(sv.HasGlobalScope(), IsFalse)
 }
+
+func (*testSysVarSuite) TestBuiltInCase(c *C) {
+	// All Sysvars should have lower case names.
+	// This tests builtins.
+	for name := range GetSysVars() {
+		c.Assert(name, Equals, strings.ToLower(name))
+	}
+}
+
+func (*testSysVarSuite) TestSQLSelectLimit(c *C) {
+	sv := GetSysVar(SQLSelectLimit)
+	vars := NewSessionVars()
+	val, err := sv.Validate(vars, "-10", ScopeSession)
+	c.Assert(err, IsNil) // it has autoconvert out of range.
+	c.Assert(val, Equals, "0")
+
+	val, err = sv.Validate(vars, "9999", ScopeSession)
+	c.Assert(err, IsNil)
+	c.Assert(val, Equals, "9999")
+
+	c.Assert(sv.SetSessionFromHook(vars, "9999"), IsNil) // sets
+	c.Assert(vars.SelectLimit, Equals, uint64(9999))
+}
+
+func (*testSysVarSuite) TestSQLModeVar(c *C) {
+	sv := GetSysVar(SQLModeVar)
+	vars := NewSessionVars()
+	val, err := sv.Validate(vars, "strict_trans_tabLES  ", ScopeSession)
+	c.Assert(err, IsNil)
+	c.Assert(val, Equals, "STRICT_TRANS_TABLES")
+
+	_, err = sv.Validate(vars, "strict_trans_tabLES,nonsense_option", ScopeSession)
+	c.Assert(err.Error(), Equals, "ERROR 1231 (42000): Variable 'sql_mode' can't be set to the value of 'NONSENSE_OPTION'")
+
+	val, err = sv.Validate(vars, "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION", ScopeSession)
+	c.Assert(err, IsNil)
+	c.Assert(val, Equals, "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION")
+
+	c.Assert(sv.SetSessionFromHook(vars, val), IsNil) // sets to strict from above
+	c.Assert(vars.StrictSQLMode, IsTrue)
+
+	sqlMode, err := mysql.GetSQLMode(val)
+	c.Assert(err, IsNil)
+	c.Assert(vars.SQLMode, Equals, sqlMode)
+
+	// Set it to non strict.
+	val, err = sv.Validate(vars, "ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION", ScopeSession)
+	c.Assert(err, IsNil)
+	c.Assert(val, Equals, "ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION")
+
+	c.Assert(sv.SetSessionFromHook(vars, val), IsNil) // sets to non-strict from above
+	c.Assert(vars.StrictSQLMode, IsFalse)
+	sqlMode, err = mysql.GetSQLMode(val)
+	c.Assert(err, IsNil)
+	c.Assert(vars.SQLMode, Equals, sqlMode)
+}
+
+func (*testSysVarSuite) TestMaxExecutionTime(c *C) {
+	sv := GetSysVar(MaxExecutionTime)
+	vars := NewSessionVars()
+
+	val, err := sv.Validate(vars, "-10", ScopeSession)
+	c.Assert(err, IsNil) // it has autoconvert out of range.
+	c.Assert(val, Equals, "0")
+
+	val, err = sv.Validate(vars, "99999", ScopeSession)
+	c.Assert(err, IsNil) // it has autoconvert out of range.
+	c.Assert(val, Equals, "99999")
+
+	c.Assert(sv.SetSessionFromHook(vars, "99999"), IsNil) // sets
+	c.Assert(vars.MaxExecutionTime, Equals, uint64(99999))
+}
+
+func (*testSysVarSuite) TestCollationServer(c *C) {
+	sv := GetSysVar(CollationServer)
+	vars := NewSessionVars()
+
+	val, err := sv.Validate(vars, "LATIN1_bin", ScopeSession)
+	c.Assert(err, IsNil)
+	c.Assert(val, Equals, "latin1_bin") // test normalization
+
+	_, err = sv.Validate(vars, "BOGUSCOLLation", ScopeSession)
+	c.Assert(err.Error(), Equals, "[ddl:1273]Unknown collation: 'BOGUSCOLLation'")
+
+	c.Assert(sv.SetSessionFromHook(vars, "latin1_bin"), IsNil)
+	c.Assert(vars.systems[CharacterSetServer], Equals, "latin1") // check it also changes charset.
+
+	c.Assert(sv.SetSessionFromHook(vars, "utf8mb4_bin"), IsNil)
+	c.Assert(vars.systems[CharacterSetServer], Equals, "utf8mb4") // check it also changes charset.
+}