107 lines
3.9 KiB
Go
107 lines
3.9 KiB
Go
// Command i18n_migrate 落地方案 A 的 i18n 列(加列 + 回填)。
|
||
//
|
||
// 项目已移除 AutoMigrate,表结构由外部 SQL 托管(见 scripts/sql/002_i18n_columns.sql,
|
||
// 那是给人 review 的规范底稿)。本程序是「没有 mysql 客户端时」的执行器:
|
||
// - ALTER 走 ensureColumn:先查 information_schema,缺才加,可安全重跑(幂等)。
|
||
// - 回填 UPDATE 内联且幂等,重跑无害。
|
||
//
|
||
// 不写任何业务逻辑。
|
||
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"log"
|
||
|
||
"gorm.io/driver/mysql"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
const dsn = "root:root@tcp(127.0.0.1:3306)/db?charset=utf8mb4&parseTime=True&loc=Local"
|
||
const han = "[一-鿿]"
|
||
|
||
func main() {
|
||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||
if err != nil {
|
||
log.Fatal("open:", err)
|
||
}
|
||
|
||
// 1) 幂等加列(与 002_i18n_columns.sql 对齐)
|
||
ensureColumn(db, "brand", "name_en", "VARCHAR(255) NOT NULL DEFAULT '' AFTER name")
|
||
ensureColumn(db, "brand", "name_cn", "VARCHAR(255) NOT NULL DEFAULT '' AFTER name_en")
|
||
ensureColumn(db, "brand_runway", "title_en", "VARCHAR(255) NOT NULL DEFAULT '' AFTER title")
|
||
ensureColumn(db, "brand_runway", "title_cn", "VARCHAR(255) NOT NULL DEFAULT '' AFTER title_en")
|
||
ensureColumn(db, "brand_runway", "description_en", "VARCHAR(1024) NOT NULL DEFAULT '' AFTER description")
|
||
ensureColumn(db, "brand_runway", "description_cn", "VARCHAR(1024) NOT NULL DEFAULT '' AFTER description_en")
|
||
|
||
// 2) 回填品牌名:从 name / show_name 拆拉丁与中文(幂等)
|
||
db.Exec(fmt.Sprintf(`
|
||
UPDATE brand SET
|
||
name_en = CASE
|
||
WHEN TRIM(REGEXP_REPLACE(name, '%s', '')) <> '' THEN TRIM(REGEXP_REPLACE(name, '%s', ''))
|
||
WHEN show_name LIKE '%%/%%' THEN TRIM(SUBSTRING_INDEX(show_name, '/', 1))
|
||
ELSE ''
|
||
END,
|
||
name_cn = CASE
|
||
WHEN show_name LIKE '%%/%%' AND SUBSTRING_INDEX(show_name, '/', -1) REGEXP '%s'
|
||
THEN TRIM(SUBSTRING_INDEX(show_name, '/', -1))
|
||
WHEN show_name REGEXP '%s' THEN TRIM(show_name)
|
||
WHEN name REGEXP '%s' THEN TRIM(name)
|
||
ELSE ''
|
||
END`, han, han, han, han, han))
|
||
|
||
// 3) 回填走秀:title / description 当前全英文,直接进 *_en(幂等)
|
||
db.Exec(`UPDATE brand_runway SET title_en = title, description_en = description, title_cn = '', description_cn = ''`)
|
||
|
||
// 4) 校验
|
||
printCounts(db)
|
||
fmt.Println("migration done.")
|
||
}
|
||
|
||
func ensureColumn(db *gorm.DB, table, col, def string) {
|
||
var n int64
|
||
db.Raw("SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='db' AND TABLE_NAME=? AND COLUMN_NAME=?", table, col).Scan(&n)
|
||
if n > 0 {
|
||
fmt.Printf(" skip %s.%s (exists)\n", table, col)
|
||
return
|
||
}
|
||
stmt := fmt.Sprintf("ALTER TABLE %s ADD COLUMN %s %s", table, col, def)
|
||
fmt.Println(" +", stmt)
|
||
if r := db.Exec(stmt); r.Error != nil {
|
||
log.Fatalf("alter %s.%s failed: %v", table, col, r.Error)
|
||
}
|
||
}
|
||
|
||
func printCounts(db *gorm.DB) {
|
||
type c struct {
|
||
Tot, En, Cn, Both, Dcn int64
|
||
}
|
||
var b c
|
||
db.Raw(`SELECT COUNT(*) tot,
|
||
SUM(CASE WHEN name_en<>'' THEN 1 ELSE 0 END) en,
|
||
SUM(CASE WHEN name_cn<>'' THEN 1 ELSE 0 END) cn,
|
||
SUM(CASE WHEN name_en<>'' AND name_cn<>'' THEN 1 ELSE 0 END) both_cnt
|
||
FROM brand`).Scan(&b)
|
||
fmt.Printf(" brand: total=%d name_en=%d name_cn=%d both=%d\n", b.Tot, b.En, b.Cn, b.Both)
|
||
|
||
var r c
|
||
db.Raw(`SELECT COUNT(*) tot,
|
||
SUM(CASE WHEN title_en<>'' THEN 1 ELSE 0 END) en,
|
||
SUM(CASE WHEN title_cn<>'' THEN 1 ELSE 0 END) cn,
|
||
SUM(CASE WHEN description_cn<>'' THEN 1 ELSE 0 END) dcn
|
||
FROM brand_runway WHERE is_deleted=0`).Scan(&r)
|
||
fmt.Printf(" runway: total=%d title_en=%d title_cn=%d desc_cn=%d\n", r.Tot, r.En, r.Cn, r.Dcn)
|
||
|
||
type s struct {
|
||
Name string
|
||
ShowName string
|
||
NameEn string
|
||
NameCn string
|
||
}
|
||
var samples []s
|
||
db.Raw("SELECT name, show_name, name_en, name_cn FROM brand WHERE name REGEXP ? OR show_name REGEXP ? ORDER BY id LIMIT 8", han, han).Scan(&samples)
|
||
fmt.Println(" brand samples:")
|
||
for _, x := range samples {
|
||
fmt.Printf(" name=%-18q show=%-26q -> en=%-18q cn=%-18q\n", x.Name, x.ShowName, x.NameEn, x.NameCn)
|
||
}
|
||
}
|