feat: 支持无SKU目录导入策略 (#141)
This commit is contained in:
@@ -5,11 +5,14 @@ import (
|
||||
"crypto/sha256"
|
||||
"database/sql"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cmautobuy/admin/spec"
|
||||
)
|
||||
|
||||
// SQLiteMigrationSummary 只包含表名和数量,可以安全写入终端或工单。
|
||||
@@ -117,6 +120,9 @@ func MigrateSQLiteToMySQL(source, target *sql.DB, dryRun bool) (*SQLiteMigration
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := normalizeMigratedShopeeSKUs(tx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, &SQLiteMigrationError{Stage: "无法提交 MySQL 导入事务", Cause: err}
|
||||
}
|
||||
@@ -126,6 +132,52 @@ func MigrateSQLiteToMySQL(source, target *sql.DB, dryRun bool) (*SQLiteMigration
|
||||
return summary, nil
|
||||
}
|
||||
|
||||
// normalizeMigratedShopeeSKUs 补齐 MySQL v8 新增、历史 SQLite 没有的规格身份列。
|
||||
func normalizeMigratedShopeeSKUs(tx *sql.Tx) error {
|
||||
rows, err := tx.Query(`SELECT sku_id,spec_raw,color,size,advice,sku_code,updated_at FROM shopee_skus`)
|
||||
if err != nil {
|
||||
return &SQLiteMigrationError{Stage: "无法读取待转换 SKU", Table: "shopee_skus", Cause: err}
|
||||
}
|
||||
type item struct {
|
||||
id, raw, updated string
|
||||
color, size, advice, code sql.NullString
|
||||
}
|
||||
var list []item
|
||||
for rows.Next() {
|
||||
var row item
|
||||
if err := rows.Scan(&row.id, &row.raw, &row.color, &row.size, &row.advice, &row.code, &row.updated); err != nil {
|
||||
rows.Close()
|
||||
return err
|
||||
}
|
||||
list = append(list, row)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, row := range list {
|
||||
key, err := spec.SpecKey(row.raw)
|
||||
if err != nil {
|
||||
return &SQLiteMigrationError{Stage: "历史 SKU 规格原文无效", Table: "shopee_skus", Cause: err}
|
||||
}
|
||||
if len([]rune(key)) > 191 {
|
||||
return &SQLiteMigrationError{Stage: "历史 SKU 规格键过长", Table: "shopee_skus"}
|
||||
}
|
||||
sources, times := map[string]string{}, map[string]string{}
|
||||
for name, value := range map[string]string{"color": row.color.String, "size": row.size.String, "advice": row.advice.String, "sku_code": row.code.String} {
|
||||
if value != "" {
|
||||
sources[name] = "report"
|
||||
times[name] = row.updated
|
||||
}
|
||||
}
|
||||
sourcesJSON, _ := json.Marshal(sources)
|
||||
timesJSON, _ := json.Marshal(times)
|
||||
if _, err := tx.Exec(`UPDATE shopee_skus SET shopee_sku_id=sku_id,spec_key=?,source='report',field_sources=?,field_observed_at=? WHERE sku_id=?`, key, string(sourcesJSON), string(timesJSON), row.id); err != nil {
|
||||
return &SQLiteMigrationError{Stage: "无法补齐 MySQL v8 SKU 身份", Table: "shopee_skus", Cause: err}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifySQLiteToMySQL 比较逐表数量和全部迁移列的确定性摘要,不输出业务内容。
|
||||
func VerifySQLiteToMySQL(source, target *sql.DB) (*SQLiteMigrationSummary, error) {
|
||||
if err := validateLegacySQLite(source); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user