package data import ( "fmt" "gorm.io/gorm" ) func migrateAll(db *gorm.DB) error { if err := db.AutoMigrate( &userPO{}, &authorityPO{}, &menuPO{}, &userAuthorityPO{}, &authorityMenuPO{}, &menuParameterPO{}, &apiPO{}, &ignoredAPIPO{}, &authorityAPIPO{}, &menuButtonPO{}, &authorityButtonPO{}, &departmentPO{}, &positionPO{}, &userDepartmentPO{}, &userPositionPO{}, &authorityDepartmentPO{}, &dictionaryPO{}, &dictionaryDetailPO{}, ¶meterPO{}, &apiTokenPO{}, &jwtBlacklistPO{}, &securityConfigPO{}, &versionPO{}, &exportTemplatePO{}, &exportConditionPO{}, &exportJoinPO{}, &operationPO{}, &loginLogPO{}, &dataAccessLogPO{}, &errorRecordPO{}, &taskPO{}, &taskLogPO{}, &mediaPO{}, &categoryPO{}, &uploadSessionPO{}, &uploadChunkPO{}, &announcementPO{}, ); err != nil { return err } return reconcileReferenceIndexes(db) } // reconcileReferenceIndexes removes constraints created by older Kra builds // that are not part of the administration data model. Business services own // duplicate checks and their user-facing error messages. func reconcileReferenceIndexes(db *gorm.DB) error { obsolete := []struct { model any name string }{ {&apiPO{}, "idx_api_path_method"}, {&dictionaryPO{}, "idx_sys_dictionaries_type"}, {¶meterPO{}, "idx_sys_params_key"}, {&apiTokenPO{}, "idx_sys_api_tokens_token"}, {&exportTemplatePO{}, "idx_sys_export_templates_template_id"}, } for _, item := range obsolete { if db.Migrator().HasIndex(item.model, item.name) { if err := db.Migrator().DropIndex(item.model, item.name); err != nil { return fmt.Errorf("drop obsolete index %s: %w", item.name, err) } } } for _, item := range []struct { name string field string }{{"idx_sys_users_uuid", "UUID"}, {"idx_sys_users_username", "Username"}} { unique, err := indexIsUnique(db, &userPO{}, item.name) if err != nil { return err } if !unique { continue } if err = db.Migrator().DropIndex(&userPO{}, item.name); err != nil { return fmt.Errorf("drop legacy unique index %s: %w", item.name, err) } if err = db.Migrator().CreateIndex(&userPO{}, item.field); err != nil { return fmt.Errorf("create reference index %s: %w", item.name, err) } } return nil } func indexIsUnique(db *gorm.DB, model any, name string) (bool, error) { indexes, err := db.Migrator().GetIndexes(model) if err != nil { // Some third-party GORM drivers do not implement index inspection. // Fresh schemas are already correct; skip only the legacy repair there. return false, nil } for _, index := range indexes { if index.Name() == name { unique, known := index.Unique() return known && unique, nil } } return false, nil }