|
@@ -389,12 +389,7 @@ func CloseDB() error {
|
|
|
// default charset/collation can store Chinese characters. It allows common
|
|
// default charset/collation can store Chinese characters. It allows common
|
|
|
// Chinese-capable charsets (utf8mb4, utf8, gbk, big5, gb18030) and panics otherwise.
|
|
// Chinese-capable charsets (utf8mb4, utf8, gbk, big5, gb18030) and panics otherwise.
|
|
|
func checkMySQLChineseSupport(db *gorm.DB) error {
|
|
func checkMySQLChineseSupport(db *gorm.DB) error {
|
|
|
- // Read session/server variables
|
|
|
|
|
- var charsetServer, collationServer, charsetDBVar, collationDBVar, charsetConn, collationConn string
|
|
|
|
|
- row := db.Raw("SELECT @@character_set_server, @@collation_server, @@character_set_database, @@collation_database, @@character_set_connection, @@collation_connection").Row()
|
|
|
|
|
- if err := row.Scan(&charsetServer, &collationServer, &charsetDBVar, &collationDBVar, &charsetConn, &collationConn); err != nil {
|
|
|
|
|
- return fmt.Errorf("读取 MySQL 字符集变量失败 / Failed to read MySQL charset variables: %v", err)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 仅检测:当前库默认字符集/排序规则 + 各表的排序规则(隐含字符集)
|
|
|
|
|
|
|
|
// Read current schema defaults
|
|
// Read current schema defaults
|
|
|
var schemaCharset, schemaCollation string
|
|
var schemaCharset, schemaCollation string
|
|
@@ -416,20 +411,68 @@ func checkMySQLChineseSupport(db *gorm.DB) error {
|
|
|
csLower := toLower(cs)
|
|
csLower := toLower(cs)
|
|
|
clLower := toLower(cl)
|
|
clLower := toLower(cl)
|
|
|
if prefix, ok := allowedCharsets[csLower]; ok {
|
|
if prefix, ok := allowedCharsets[csLower]; ok {
|
|
|
- // collation should correspond to the charset when available
|
|
|
|
|
if clLower == "" {
|
|
if clLower == "" {
|
|
|
return true
|
|
return true
|
|
|
}
|
|
}
|
|
|
return strings.HasPrefix(clLower, prefix)
|
|
return strings.HasPrefix(clLower, prefix)
|
|
|
}
|
|
}
|
|
|
|
|
+ // 如果仅提供了排序规则,尝试按排序规则前缀判断
|
|
|
|
|
+ for _, prefix := range allowedCharsets {
|
|
|
|
|
+ if strings.HasPrefix(clLower, prefix) {
|
|
|
|
|
+ return true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // We strictly require the CONNECTION and SCHEMA defaults to be Chinese-capable.
|
|
|
|
|
- // We also check database/server variables and include them in the error for visibility.
|
|
|
|
|
- if !isChineseCapable(charsetConn, collationConn) || !isChineseCapable(schemaCharset, schemaCollation) || !isChineseCapable(charsetDBVar, collationDBVar) {
|
|
|
|
|
- return fmt.Errorf("MySQL 字符集/排序规则必须支持中文(允许 utf8mb4/utf8/gbk/big5/gb18030),请调整服务器、数据库或连接设置。/ MySQL charset/collation must be Chinese-capable (one of utf8mb4/utf8/gbk/big5/gb18030). Details: server(%s/%s), database_var(%s/%s), connection(%s/%s), schema(%s/%s)",
|
|
|
|
|
- charsetServer, collationServer, charsetDBVar, collationDBVar, charsetConn, collationConn, schemaCharset, schemaCollation)
|
|
|
|
|
|
|
+ // 1) 当前库默认值必须支持中文
|
|
|
|
|
+ if !isChineseCapable(schemaCharset, schemaCollation) {
|
|
|
|
|
+ return fmt.Errorf("当前库默认字符集/排序规则不支持中文:schema(%s/%s)。请将库设置为 utf8mb4/utf8/gbk/big5/gb18030 / Schema default charset/collation is not Chinese-capable: schema(%s/%s). Please set to utf8mb4/utf8/gbk/big5/gb18030",
|
|
|
|
|
+ schemaCharset, schemaCollation, schemaCharset, schemaCollation)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2) 所有物理表的排序规则(隐含字符集)必须支持中文
|
|
|
|
|
+ type tableInfo struct {
|
|
|
|
|
+ Name string
|
|
|
|
|
+ Collation *string
|
|
|
|
|
+ }
|
|
|
|
|
+ var tables []tableInfo
|
|
|
|
|
+ if err := db.Raw("SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE'").Scan(&tables).Error; err != nil {
|
|
|
|
|
+ return fmt.Errorf("读取表排序规则失败 / Failed to read table collations: %v", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var badTables []string
|
|
|
|
|
+ for _, t := range tables {
|
|
|
|
|
+ // NULL 或空表示继承库默认设置,已在上面校验库默认,视为通过
|
|
|
|
|
+ if t.Collation == nil || *t.Collation == "" {
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ cl := *t.Collation
|
|
|
|
|
+ // 仅凭排序规则判断是否中文可用
|
|
|
|
|
+ ok := false
|
|
|
|
|
+ lower := strings.ToLower(cl)
|
|
|
|
|
+ for _, prefix := range allowedCharsets {
|
|
|
|
|
+ if strings.HasPrefix(lower, prefix) {
|
|
|
|
|
+ ok = true
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if !ok {
|
|
|
|
|
+ badTables = append(badTables, fmt.Sprintf("%s(%s)", t.Name, cl))
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if len(badTables) > 0 {
|
|
|
|
|
+ // 限制输出数量以避免日志过长
|
|
|
|
|
+ maxShow := 20
|
|
|
|
|
+ shown := badTables
|
|
|
|
|
+ if len(shown) > maxShow {
|
|
|
|
|
+ shown = shown[:maxShow]
|
|
|
|
|
+ }
|
|
|
|
|
+ return fmt.Errorf(
|
|
|
|
|
+ "存在不支持中文的表,请修复其排序规则/字符集。示例(最多展示 %d 项):%v / Found tables not Chinese-capable. Please fix their collation/charset. Examples (showing up to %d): %v",
|
|
|
|
|
+ maxShow, shown, maxShow, shown,
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
return nil
|
|
return nil
|
|
|
}
|
|
}
|