Skip to content

Commit 747abcd

Browse files
committed
skip uuid migration if not needed
1 parent 5563b1f commit 747abcd

File tree

2 files changed

+72
-78
lines changed

2 files changed

+72
-78
lines changed

aiplan.go/cmd/aiplan/main.go

Lines changed: 72 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -111,82 +111,87 @@ func main() {
111111
}
112112
slog.Info("Filtered migratable columns", "count", len(columnsToMigrate), "skipped", len(allColumns)-len(columnsToMigrate))
113113

114-
// Execute all migrations in a single transaction
115-
err = dbForMigration.Transaction(func(tx *gorm.DB) error {
116-
// Step 1: Drop all generated columns (they block type changes)
117-
slog.Info("Dropping all generated columns")
118-
if err := dao.DropAllGeneratedColumns(tx); err != nil {
119-
return fmt.Errorf("failed to drop generated columns: %w", err)
120-
}
121-
slog.Info("All generated columns dropped")
122-
123-
// Step 2: Clean orphaned foreign keys (пока FK ещё существуют в БД)
124-
slog.Info("Cleaning orphaned foreign keys")
125-
if err := dao.CleanAllOrphanedForeignKeys(tx); err != nil {
126-
return fmt.Errorf("failed to clean all orphaned foreign keys: %w", err)
127-
}
128-
slog.Info("All orphaned foreign keys cleaned")
114+
// Пропускаем UUID миграцию если нет колонок для миграции
115+
if len(columnsToMigrate) > 0 {
116+
// Execute all migrations in a single transaction
117+
err = dbForMigration.Transaction(func(tx *gorm.DB) error {
118+
// Step 1: Drop all generated columns (they block type changes)
119+
slog.Info("Dropping all generated columns")
120+
if err := dao.DropAllGeneratedColumns(tx); err != nil {
121+
return fmt.Errorf("failed to drop generated columns: %w", err)
122+
}
123+
slog.Info("All generated columns dropped")
129124

130-
// Step 3: Drop all FK constraints
131-
slog.Info("Dropping all foreign key constraints")
132-
if err := dao.DropAllForeignKeys(tx); err != nil {
133-
return fmt.Errorf("failed to drop foreign keys: %w", err)
134-
}
135-
slog.Info("All foreign key constraints dropped")
125+
// Step 2: Clean orphaned foreign keys (пока FK ещё существуют в БД)
126+
slog.Info("Cleaning orphaned foreign keys")
127+
if err := dao.CleanAllOrphanedForeignKeys(tx); err != nil {
128+
return fmt.Errorf("failed to clean all orphaned foreign keys: %w", err)
129+
}
130+
slog.Info("All orphaned foreign keys cleaned")
136131

137-
// Step 4: Drop all CHECK constraints (including linked_issues check:id1<id2)
138-
slog.Info("Dropping all check constraints")
139-
if err := dao.DropAllCheckConstraints(tx); err != nil {
140-
return fmt.Errorf("failed to drop check constraints: %w", err)
141-
}
142-
slog.Info("All check constraints dropped")
132+
// Step 3: Drop all FK constraints
133+
slog.Info("Dropping all foreign key constraints")
134+
if err := dao.DropAllForeignKeys(tx); err != nil {
135+
return fmt.Errorf("failed to drop foreign keys: %w", err)
136+
}
137+
slog.Info("All foreign key constraints dropped")
143138

144-
// Step 5: Clean invalid UUIDs (set to NULL)
145-
slog.Info("Cleaning invalid UUID values", "count", len(columnsToMigrate))
146-
for _, col := range columnsToMigrate {
147-
if err := dao.CleanInvalidUUIDs(tx, col.Table, col.Column); err != nil {
148-
return fmt.Errorf("failed to clean invalid UUIDs in %s.%s: %w", col.Table, col.Column, err)
139+
// Step 4: Drop all CHECK constraints (including linked_issues check:id1<id2)
140+
slog.Info("Dropping all check constraints")
141+
if err := dao.DropAllCheckConstraints(tx); err != nil {
142+
return fmt.Errorf("failed to drop check constraints: %w", err)
149143
}
150-
}
151-
slog.Info("All invalid UUIDs cleaned")
152-
153-
// Step 6: Replace column types
154-
slog.Info("Replacing column types", "count", len(columnsToMigrate))
155-
for _, col := range columnsToMigrate {
156-
slog.Info("Migrating column", "table", col.Table, "column", col.Column, "currentType", col.CurrentType)
157-
if err := utils.ReplaceColumnTypeWithCast(tx, col, "uuid"); err != nil {
158-
return fmt.Errorf("failed to replace column %s.%s (type %s): %w", col.Table, col.Column, col.CurrentType, err)
144+
slog.Info("All check constraints dropped")
145+
146+
// Step 5: Clean invalid UUIDs (set to NULL)
147+
slog.Info("Cleaning invalid UUID values", "count", len(columnsToMigrate))
148+
for _, col := range columnsToMigrate {
149+
if err := dao.CleanInvalidUUIDs(tx, col.Table, col.Column); err != nil {
150+
return fmt.Errorf("failed to clean invalid UUIDs in %s.%s: %w", col.Table, col.Column, err)
151+
}
159152
}
160-
}
161-
slog.Info("All column types replaced successfully")
162-
163-
// Step 7: Clean known self-referencing FK (они могли не существовать в БД)
164-
slog.Info("Cleaning known self-referencing foreign keys")
165-
selfRefFKs := []struct {
166-
Table string
167-
Column string
168-
ReferencedTable string
169-
ReferencedColumn string
170-
}{
171-
{"issues", "parent_id", "issues", "id"},
172-
{"docs", "parent_id", "docs", "id"},
173-
{"doc_fields", "parent_id", "doc_fields", "id"},
174-
}
175-
for _, fk := range selfRefFKs {
176-
if err := dao.CleanOrphanedForeignKeys(tx, fk.Table, fk.Column, fk.ReferencedTable, fk.ReferencedColumn); err != nil {
177-
slog.Warn("Failed to clean self-referencing FK", "table", fk.Table, "column", fk.Column, "err", err)
153+
slog.Info("All invalid UUIDs cleaned")
154+
155+
// Step 6: Replace column types
156+
slog.Info("Replacing column types", "count", len(columnsToMigrate))
157+
for _, col := range columnsToMigrate {
158+
slog.Info("Migrating column", "table", col.Table, "column", col.Column, "currentType", col.CurrentType)
159+
if err := utils.ReplaceColumnTypeWithCast(tx, col, "uuid"); err != nil {
160+
return fmt.Errorf("failed to replace column %s.%s (type %s): %w", col.Table, col.Column, col.CurrentType, err)
161+
}
178162
}
179-
}
180-
slog.Info("Self-referencing foreign keys cleaned")
163+
slog.Info("All column types replaced successfully")
164+
165+
// Step 7: Clean known self-referencing FK (они могли не существовать в БД)
166+
slog.Info("Cleaning known self-referencing foreign keys")
167+
selfRefFKs := []struct {
168+
Table string
169+
Column string
170+
ReferencedTable string
171+
ReferencedColumn string
172+
}{
173+
{"issues", "parent_id", "issues", "id"},
174+
{"docs", "parent_id", "docs", "id"},
175+
{"doc_fields", "parent_id", "doc_fields", "id"},
176+
}
177+
for _, fk := range selfRefFKs {
178+
if err := dao.CleanOrphanedForeignKeys(tx, fk.Table, fk.Column, fk.ReferencedTable, fk.ReferencedColumn); err != nil {
179+
slog.Warn("Failed to clean self-referencing FK", "table", fk.Table, "column", fk.Column, "err", err)
180+
}
181+
}
182+
slog.Info("Self-referencing foreign keys cleaned")
181183

182-
return nil
183-
})
184+
return nil
185+
})
184186

185-
if err != nil {
186-
slog.Error("UUID migration failed", "err", err)
187-
os.Exit(1)
187+
if err != nil {
188+
slog.Error("UUID migration failed", "err", err)
189+
os.Exit(1)
190+
}
191+
slog.Info("UUID migration completed successfully")
192+
} else {
193+
slog.Info("No UUID columns need migration, skipping UUID migration steps")
188194
}
189-
slog.Info("UUID migration completed successfully")
190195

191196
// Step 8: AutoMigrate models (в отдельной транзакции)
192197
err = dbForMigration.Transaction(func(tx *gorm.DB) error {

aiplan.go/internal/aiplan/utils/postgres_uuid_dialector.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package utils
33

44
import (
55
"fmt"
6-
"log/slog"
76
"reflect"
87
"strings"
98

@@ -93,23 +92,13 @@ func (m *PostgresUUIDMigrator) AlterColumn(value interface{}, field string) erro
9392
// Если колонка уже имеет тип uuid, не изменяем её
9493
databaseType := columnType.DatabaseTypeName()
9594

96-
// Debug logging
97-
slog.Info("AlterColumn check",
98-
"table", stmt.Table,
99-
"column", schemaField.DBName,
100-
"dbType", databaseType,
101-
"wantType", m.DataTypeOf(schemaField))
102-
10395
if strings.EqualFold(databaseType, "uuid") {
10496
fieldType := schemaField.FieldType
10597
if fieldType.Kind() == reflect.Pointer {
10698
fieldType = fieldType.Elem()
10799
}
108100
if fieldType == reflect.TypeOf(uuid.UUID{}) || fieldType == reflect.TypeOf(uuid.NullUUID{}) {
109101
// Колонка уже uuid и поле тоже uuid - пропускаем изменение
110-
slog.Info("Skipping AlterColumn (already uuid)",
111-
"table", stmt.Table,
112-
"column", schemaField.DBName)
113102
return nil
114103
}
115104
}

0 commit comments

Comments
 (0)