fix(codegen): sort map iteration to make generated output deterministic
Table.Columns/Constraints/Indexes/Relationships are Go maps, and every writer, reader, diff, inspector, and merge code path that iterated them directly was subject to Go's randomized map order, so identical input could produce different output (or a different in-report violation/diff order) on every run. Most visibly this showed up as bun/gorm `unique:` struct tags changing order across consecutive `make models` runs with no source change. Fixed by sorting map iteration (by Sequence then Name, or alphabetically for string-keyed maps) everywhere the order affects generated output or first-match tie-break logic, across the bun, gorm, sqlite, dbml, drawdb, pgsql, prisma, graphql, typeorm, drizzle, and dctx writers; the dctx, prisma, and typeorm readers; the shared models.GetPrimaryKey/ GetForeignKeys helpers; pkg/diff, pkg/inspector, and pkg/merge; and the TUI column/relationship pickers in pkg/ui.
This commit is contained in:
@@ -239,7 +239,8 @@ func (w *MigrationWriter) generateDropScripts(model *models.Schema, current *mod
|
||||
}
|
||||
|
||||
// Check each constraint in current database
|
||||
for constraintName, currentConstraint := range currentTable.Constraints {
|
||||
for _, currentConstraint := range sortConstraints(currentTable.Constraints) {
|
||||
constraintName := currentConstraint.Name
|
||||
modelConstraint, existsInModel := modelTable.Constraints[constraintName]
|
||||
|
||||
shouldDrop := false
|
||||
@@ -252,7 +253,8 @@ func (w *MigrationWriter) generateDropScripts(model *models.Schema, current *mod
|
||||
if shouldDrop && currentConstraint.Type == models.PrimaryKeyConstraint {
|
||||
// Drop FK constraints that depend on this PK before dropping the PK itself.
|
||||
for _, otherTable := range current.Tables {
|
||||
for fkName, fkConstraint := range otherTable.Constraints {
|
||||
for _, fkConstraint := range sortConstraints(otherTable.Constraints) {
|
||||
fkName := fkConstraint.Name
|
||||
if fkConstraint.Type != models.ForeignKeyConstraint {
|
||||
continue
|
||||
}
|
||||
@@ -310,7 +312,8 @@ func (w *MigrationWriter) generateDropScripts(model *models.Schema, current *mod
|
||||
}
|
||||
|
||||
// Check indexes
|
||||
for indexName, currentIndex := range currentTable.Indexes {
|
||||
for _, currentIndex := range sortIndexes(currentTable.Indexes) {
|
||||
indexName := currentIndex.Name
|
||||
modelIndex, existsInModel := modelTable.Indexes[indexName]
|
||||
|
||||
shouldDrop := false
|
||||
@@ -401,7 +404,7 @@ func (w *MigrationWriter) generateAlterTableScripts(schema *models.Schema, model
|
||||
}
|
||||
|
||||
// Check each model column
|
||||
for _, modelCol := range modelTable.Columns {
|
||||
for _, modelCol := range sortColumns(modelTable.Columns) {
|
||||
currentCol, exists := currentColumns[strings.ToLower(modelCol.Name)]
|
||||
|
||||
if !exists {
|
||||
@@ -518,7 +521,8 @@ func (w *MigrationWriter) generateIndexScripts(model *models.Schema, current *mo
|
||||
|
||||
// Process primary keys first - check explicit constraints
|
||||
foundExplicitPK := false
|
||||
for constraintName, constraint := range modelTable.Constraints {
|
||||
for _, constraint := range sortConstraints(modelTable.Constraints) {
|
||||
constraintName := constraint.Name
|
||||
if constraint.Type == models.PrimaryKeyConstraint {
|
||||
foundExplicitPK = true
|
||||
shouldCreate := true
|
||||
@@ -603,7 +607,8 @@ func (w *MigrationWriter) generateIndexScripts(model *models.Schema, current *mo
|
||||
}
|
||||
|
||||
// Process indexes
|
||||
for indexName, modelIndex := range modelTable.Indexes {
|
||||
for _, modelIndex := range sortIndexes(modelTable.Indexes) {
|
||||
indexName := modelIndex.Name
|
||||
// Skip primary key indexes
|
||||
if strings.HasPrefix(strings.ToLower(indexName), "pk_") {
|
||||
continue
|
||||
@@ -697,7 +702,8 @@ func (w *MigrationWriter) generateForeignKeyScripts(model *models.Schema, curren
|
||||
currentTable := currentTables[strings.ToLower(modelTable.Name)]
|
||||
|
||||
// Process each constraint
|
||||
for constraintName, constraint := range modelTable.Constraints {
|
||||
for _, constraint := range sortConstraints(modelTable.Constraints) {
|
||||
constraintName := constraint.Name
|
||||
if constraint.Type != models.ForeignKeyConstraint {
|
||||
continue
|
||||
}
|
||||
@@ -787,7 +793,7 @@ func (w *MigrationWriter) generateCommentScripts(model *models.Schema, current *
|
||||
}
|
||||
|
||||
// Column comments
|
||||
for _, col := range modelTable.Columns {
|
||||
for _, col := range sortColumns(modelTable.Columns) {
|
||||
if col.Description != "" {
|
||||
sql, err := w.executor.ExecuteCommentColumn(CommentColumnData{
|
||||
SchemaName: model.Name,
|
||||
|
||||
Reference in New Issue
Block a user