Skip to content

Commit aa010a0

Browse files
shaohkshaohoukun
and
shaohoukun
authored
Support to config charset and collation (#1368)
* feat(feat-config-connection-charset): support config connection charset * feat(feat-config-connection-charset): feat-config-connection-charset The ability to specify character set and collation is supported. --------- Co-authored-by: shaohoukun <[email protected]>
1 parent b1aae87 commit aa010a0

File tree

5 files changed

+32
-3
lines changed

5 files changed

+32
-3
lines changed

doc/command-line-flags.md

+3
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@ But RocksDB currently lacks a few features support compared to InnoDB:
261261

262262
When `--storage-engine=rocksdb`, `gh-ost` will make some changes necessary (e.g. sets isolation level to `READ_COMMITTED`) to support RocksDB.
263263

264+
### charset
265+
The default charset for the database connection is utf8mb4, utf8, latin1. The ability to specify character set and collation is supported, eg: utf8mb4_general_ci,utf8_general_ci,latin1.
266+
264267
### test-on-replica
265268

266269
Issue the migration on a replica; do not modify data on master. Useful for validating, testing and benchmarking. See [`testing-on-replica`](testing-on-replica.md)

go/base/context.go

+9
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,15 @@ func (this *MigrationContext) SetConnectionConfig(storageEngine string) error {
305305
return nil
306306
}
307307

308+
func (this *MigrationContext) SetConnectionCharset(charset string) {
309+
if charset == "" {
310+
charset = "utf8mb4,utf8,latin1"
311+
}
312+
313+
this.InspectorConnectionConfig.Charset = charset
314+
this.ApplierConnectionConfig.Charset = charset
315+
}
316+
308317
func getSafeTableName(baseName string, suffix string) string {
309318
name := fmt.Sprintf("_%s_%s", baseName, suffix)
310319
if len(name) <= mysql.MaxTableNameLength {

go/cmd/gh-ost/main.go

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func main() {
5757
flag.StringVar(&migrationContext.CliMasterPassword, "master-password", "", "MySQL password on master, if different from that on replica. Requires --assume-master-host")
5858
flag.StringVar(&migrationContext.ConfigFile, "conf", "", "Config file")
5959
askPass := flag.Bool("ask-pass", false, "prompt for MySQL password")
60+
charset := flag.String("charset", "utf8mb4,utf8,latin1", "The default charset for the database connection is utf8mb4, utf8, latin1.")
6061

6162
flag.BoolVar(&migrationContext.UseTLS, "ssl", false, "Enable SSL encrypted connections to MySQL hosts")
6263
flag.StringVar(&migrationContext.TLSCACertificate, "ssl-ca", "", "CA certificate in PEM format for TLS connections to MySQL hosts. Requires --ssl")
@@ -191,6 +192,8 @@ func main() {
191192
migrationContext.Log.Fatale(err)
192193
}
193194

195+
migrationContext.SetConnectionCharset(*charset)
196+
194197
if migrationContext.AlterStatement == "" {
195198
log.Fatal("--alter must be provided and statement must not be empty")
196199
}

go/mysql/connection.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type ConnectionConfig struct {
3030
tlsConfig *tls.Config
3131
Timeout float64
3232
TransactionIsolation string
33+
Charset string
3334
}
3435

3536
func NewConnectionConfig() *ConnectionConfig {
@@ -49,6 +50,7 @@ func (this *ConnectionConfig) DuplicateCredentials(key InstanceKey) *ConnectionC
4950
tlsConfig: this.tlsConfig,
5051
Timeout: this.Timeout,
5152
TransactionIsolation: this.TransactionIsolation,
53+
Charset: this.Charset,
5254
}
5355
config.ImpliedKey = &config.Key
5456
return config
@@ -122,10 +124,15 @@ func (this *ConnectionConfig) GetDBUri(databaseName string) string {
122124
if this.tlsConfig != nil {
123125
tlsOption = TLS_CONFIG_KEY
124126
}
127+
128+
if this.Charset == "" {
129+
this.Charset = "utf8mb4,utf8,latin1"
130+
}
131+
125132
connectionParams := []string{
126133
"autocommit=true",
127-
"charset=utf8mb4,utf8,latin1",
128134
"interpolateParams=true",
135+
fmt.Sprintf("charset=%s", this.Charset),
129136
fmt.Sprintf("tls=%s", tlsOption),
130137
fmt.Sprintf("transaction_isolation=%q", this.TransactionIsolation),
131138
fmt.Sprintf("timeout=%fs", this.Timeout),

go/mysql/connection_test.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func TestNewConnectionConfig(t *testing.T) {
3030
test.S(t).ExpectEquals(c.User, "")
3131
test.S(t).ExpectEquals(c.Password, "")
3232
test.S(t).ExpectEquals(c.TransactionIsolation, "")
33+
test.S(t).ExpectEquals(c.Charset, "")
3334
}
3435

3536
func TestDuplicateCredentials(t *testing.T) {
@@ -42,6 +43,7 @@ func TestDuplicateCredentials(t *testing.T) {
4243
ServerName: "feathers",
4344
}
4445
c.TransactionIsolation = transactionIsolation
46+
c.Charset = "utf8mb4"
4547

4648
dup := c.DuplicateCredentials(InstanceKey{Hostname: "otherhost", Port: 3310})
4749
test.S(t).ExpectEquals(dup.Key.Hostname, "otherhost")
@@ -52,6 +54,7 @@ func TestDuplicateCredentials(t *testing.T) {
5254
test.S(t).ExpectEquals(dup.Password, "penguin")
5355
test.S(t).ExpectEquals(dup.tlsConfig, c.tlsConfig)
5456
test.S(t).ExpectEquals(dup.TransactionIsolation, c.TransactionIsolation)
57+
test.S(t).ExpectEquals(dup.Charset, c.Charset)
5558
}
5659

5760
func TestDuplicate(t *testing.T) {
@@ -60,6 +63,7 @@ func TestDuplicate(t *testing.T) {
6063
c.User = "gromit"
6164
c.Password = "penguin"
6265
c.TransactionIsolation = transactionIsolation
66+
c.Charset = "utf8mb4"
6367

6468
dup := c.Duplicate()
6569
test.S(t).ExpectEquals(dup.Key.Hostname, "myhost")
@@ -69,6 +73,7 @@ func TestDuplicate(t *testing.T) {
6973
test.S(t).ExpectEquals(dup.User, "gromit")
7074
test.S(t).ExpectEquals(dup.Password, "penguin")
7175
test.S(t).ExpectEquals(dup.TransactionIsolation, transactionIsolation)
76+
test.S(t).ExpectEquals(dup.Charset, "utf8mb4")
7277
}
7378

7479
func TestGetDBUri(t *testing.T) {
@@ -78,9 +83,10 @@ func TestGetDBUri(t *testing.T) {
7883
c.Password = "penguin"
7984
c.Timeout = 1.2345
8085
c.TransactionIsolation = transactionIsolation
86+
c.Charset = "utf8mb4,utf8,latin1"
8187

8288
uri := c.GetDBUri("test")
83-
test.S(t).ExpectEquals(uri, `gromit:penguin@tcp(myhost:3306)/test?autocommit=true&charset=utf8mb4,utf8,latin1&interpolateParams=true&tls=false&transaction_isolation="REPEATABLE-READ"&timeout=1.234500s&readTimeout=1.234500s&writeTimeout=1.234500s`)
89+
test.S(t).ExpectEquals(uri, `gromit:penguin@tcp(myhost:3306)/test?autocommit=true&interpolateParams=true&charset=utf8mb4,utf8,latin1&tls=false&transaction_isolation="REPEATABLE-READ"&timeout=1.234500s&readTimeout=1.234500s&writeTimeout=1.234500s`)
8490
}
8591

8692
func TestGetDBUriWithTLSSetup(t *testing.T) {
@@ -91,7 +97,8 @@ func TestGetDBUriWithTLSSetup(t *testing.T) {
9197
c.Timeout = 1.2345
9298
c.tlsConfig = &tls.Config{}
9399
c.TransactionIsolation = transactionIsolation
100+
c.Charset = "utf8mb4_general_ci,utf8_general_ci,latin1"
94101

95102
uri := c.GetDBUri("test")
96-
test.S(t).ExpectEquals(uri, `gromit:penguin@tcp(myhost:3306)/test?autocommit=true&charset=utf8mb4,utf8,latin1&interpolateParams=true&tls=ghost&transaction_isolation="REPEATABLE-READ"&timeout=1.234500s&readTimeout=1.234500s&writeTimeout=1.234500s`)
103+
test.S(t).ExpectEquals(uri, `gromit:penguin@tcp(myhost:3306)/test?autocommit=true&interpolateParams=true&charset=utf8mb4_general_ci,utf8_general_ci,latin1&tls=ghost&transaction_isolation="REPEATABLE-READ"&timeout=1.234500s&readTimeout=1.234500s&writeTimeout=1.234500s`)
97104
}

0 commit comments

Comments
 (0)