Files
kra-new/internal/data/business/migration_schema.go
T

92 lines
3.7 KiB
Go

package business
import (
"fmt"
"strings"
"gorm.io/gorm"
"kra/pkg/database/migration"
)
// These source tables carry history. An incomplete copy must not be replaced
// with empty tables. SDK and OA schemas belong to their respective databases.
var importedTables = []string{
"tab_game", "tab_game_server", "tab_promote", "tab_promote_apply",
"tab_spend", "tab_user", "tab_user_day_login", "tab_user_play_info",
"tab_sw_report_day", "tab_sw_report_day_key", "tab_sw_report_server_day", "tab_sw_report_server_day_key",
}
func CheckPrerequisites(db *gorm.DB) error {
if db.Dialector.Name() != "mysql" {
return nil
}
if db.Migrator().HasTable("sys_user") && !db.Migrator().HasTable("sys_users") {
return fmt.Errorf("legacy framework conversion must run before incremental migrations")
}
var missing []string
for _, table := range importedTables {
if !db.Migrator().HasTable(table) {
missing = append(missing, table)
}
}
if len(missing) > 0 {
return fmt.Errorf("incomplete legacy copy, missing tables: %s", strings.Join(missing, ", "))
}
return nil
}
func CheckSchema(db *gorm.DB) error {
if err := CheckPrerequisites(db); err != nil {
return err
}
if err := migration.CheckModels(db,
&preferencePO{}, &bindingPO{}, &bindingLockPO{}, &resetCodePO{}, &resetTokenPO{},
&alertRulePO{}, &alertRecordPO{}, &alertLogPO{}, &alertGapPO{}, &alertExemptionPO{}, &alertChannelLockPO{},
&alertTriggerLockPO{}, &reportBuildLockPO{}, &businessGroupPO{}, &businessGroupMemberPO{},
&businessMemberProfilePO{}, &businessGroupStatePO{}, &performanceGoalPO{}, &effectivenessStatePO{}, &effectivenessPO{},
); err != nil {
return err
}
if db.Dialector.Name() != "mysql" {
return nil
}
indexes := append([]businessQueryIndex{}, businessQueryIndexes...)
var idType string
if err := db.Raw("SELECT data_type FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='tab_promote' AND column_name='id'").Scan(&idType).Error; err != nil {
return err
}
if idType != "bigint" {
return fmt.Errorf("tab_promote.id must be BIGINT after capacity migration")
}
indexes = append(indexes, reportBuildQueryIndexes...)
indexes = append(indexes, alertV2QueryIndexes...)
indexes = append(indexes,
businessQueryIndex{"tab_spend", "idx_sw_spend_effective_scan", []string{"promote_id", "source_db", "pay_status", "pay_time", "id", "pay_amount"}},
businessQueryIndex{"tab_promote_apply", "idx_sw_apply_game_scope", []string{"game_id", "source_db", "status", "promote_id"}},
businessQueryIndex{"tab_user", "idx_sw_user_registration", []string{"source_db", "puid", "sw_register_time_unix", "id"}},
businessQueryIndex{"tab_user_play_info", "idx_sw_play_create_time", []string{"create_time"}},
businessQueryIndex{"sys_alert_record", "uk_alert_record_v2_open", []string{"business_id", "platform_code", "target_promote_id", "rule_type", "v2_open_key"}},
)
for _, index := range indexes {
var existing []struct {
ColumnName string
NonUnique int
SubPart *int
}
if err := db.Raw("SELECT column_name,non_unique,sub_part FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name=? AND index_name=? ORDER BY seq_in_index", index.table, index.name).Scan(&existing).Error; err != nil {
return err
}
columns := []string{}
for _, field := range existing {
if field.SubPart != nil || index.name == "uk_alert_record_v2_open" && field.NonUnique != 0 {
return fmt.Errorf("invalid index %s.%s", index.table, index.name)
}
columns = append(columns, field.ColumnName)
}
if strings.Join(columns, ",") != strings.Join(index.columns, ",") {
return fmt.Errorf("missing or incompatible index %s.%s", index.table, index.name)
}
}
return nil
}