add build scripts and resolve migration
This commit is contained in:
106
local/migrations/004_fix_ddl_comments.go
Normal file
106
local/migrations/004_fix_ddl_comments.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"acc-server-manager/local/utl/logging"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var sqlLineCommentRegexp = regexp.MustCompile(`--[^\n]*`)
|
||||
|
||||
type Migration004FixDDLComments struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewMigration004FixDDLComments(db *gorm.DB) *Migration004FixDDLComments {
|
||||
return &Migration004FixDDLComments{DB: db}
|
||||
}
|
||||
|
||||
func (m *Migration004FixDDLComments) Up() error {
|
||||
if err := m.DB.AutoMigrate(&MigrationRecord{}); err != nil {
|
||||
return fmt.Errorf("failed to create migration tracking table: %v", err)
|
||||
}
|
||||
|
||||
var record MigrationRecord
|
||||
if err := m.DB.Where("migration_name = ?", "004_fix_ddl_comments").First(&record).Error; err == nil {
|
||||
logging.Info("DDL comment fix migration already applied, skipping")
|
||||
return nil
|
||||
}
|
||||
|
||||
var tables []string
|
||||
if err := m.DB.Raw(
|
||||
"SELECT name FROM sqlite_master WHERE type = 'table' AND sql LIKE '%--%' ORDER BY name",
|
||||
).Scan(&tables).Error; err != nil {
|
||||
return fmt.Errorf("failed to query tables with DDL comments: %v", err)
|
||||
}
|
||||
|
||||
if len(tables) == 0 {
|
||||
logging.Info("No tables with DDL comments found, skipping")
|
||||
}
|
||||
|
||||
for _, table := range tables {
|
||||
if err := m.rebuildTable(table); err != nil {
|
||||
return fmt.Errorf("failed to rebuild table %q: %v", table, err)
|
||||
}
|
||||
}
|
||||
|
||||
record = MigrationRecord{
|
||||
MigrationName: "004_fix_ddl_comments",
|
||||
AppliedAt: "datetime('now')",
|
||||
Success: true,
|
||||
Notes: fmt.Sprintf("Rebuilt %d table(s): %s", len(tables), strings.Join(tables, ", ")),
|
||||
}
|
||||
if err := m.DB.Create(&record).Error; err != nil {
|
||||
return fmt.Errorf("failed to record migration: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Migration004FixDDLComments) rebuildTable(table string) error {
|
||||
var originalDDL string
|
||||
if err := m.DB.Raw(
|
||||
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?", table,
|
||||
).Row().Scan(&originalDDL); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cleanDDL := sqlLineCommentRegexp.ReplaceAllString(originalDDL, "")
|
||||
|
||||
tmpTable := table + "__fixed"
|
||||
createTmp := strings.Replace(cleanDDL, `"`+table+`"`, "`"+tmpTable+"`", 1)
|
||||
if createTmp == cleanDDL {
|
||||
createTmp = strings.Replace(cleanDDL, table, "`"+tmpTable+"`", 1)
|
||||
}
|
||||
|
||||
logging.Info("Rebuilding table %q to remove DDL comments...", table)
|
||||
|
||||
return m.DB.Transaction(func(tx *gorm.DB) error {
|
||||
for _, sql := range []string{
|
||||
"PRAGMA foreign_keys = OFF",
|
||||
fmt.Sprintf("DROP TABLE IF EXISTS `%s`", tmpTable),
|
||||
createTmp,
|
||||
fmt.Sprintf("INSERT INTO `%s` SELECT * FROM `%s`", tmpTable, table),
|
||||
fmt.Sprintf("DROP TABLE `%s`", table),
|
||||
fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tmpTable, table),
|
||||
"PRAGMA foreign_keys = ON",
|
||||
} {
|
||||
if err := tx.Exec(sql).Error; err != nil {
|
||||
return fmt.Errorf("exec %q: %w", sql, err)
|
||||
}
|
||||
}
|
||||
logging.Info("Table %q rebuilt successfully", table)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Migration004FixDDLComments) Down() error {
|
||||
return fmt.Errorf("DDL comment fix migration rollback is not supported")
|
||||
}
|
||||
|
||||
func RunFixDDLCommentsMigration(db *gorm.DB) error {
|
||||
return NewMigration004FixDDLComments(db).Up()
|
||||
}
|
||||
Reference in New Issue
Block a user