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.
121 lines
2.9 KiB
Go
121 lines
2.9 KiB
Go
package ui
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
|
)
|
|
|
|
// Relationship data operations - business logic for relationship management
|
|
|
|
// CreateRelationship creates a new relationship and adds it to a table
|
|
func (se *SchemaEditor) CreateRelationship(schemaIndex, tableIndex int, rel *models.Relationship) *models.Relationship {
|
|
if schemaIndex < 0 || schemaIndex >= len(se.db.Schemas) {
|
|
return nil
|
|
}
|
|
|
|
schema := se.db.Schemas[schemaIndex]
|
|
if tableIndex < 0 || tableIndex >= len(schema.Tables) {
|
|
return nil
|
|
}
|
|
|
|
table := schema.Tables[tableIndex]
|
|
if table.Relationships == nil {
|
|
table.Relationships = make(map[string]*models.Relationship)
|
|
}
|
|
|
|
table.Relationships[rel.Name] = rel
|
|
table.UpdateDate()
|
|
return rel
|
|
}
|
|
|
|
// UpdateRelationship updates an existing relationship
|
|
func (se *SchemaEditor) UpdateRelationship(schemaIndex, tableIndex int, oldName string, rel *models.Relationship) bool {
|
|
if schemaIndex < 0 || schemaIndex >= len(se.db.Schemas) {
|
|
return false
|
|
}
|
|
|
|
schema := se.db.Schemas[schemaIndex]
|
|
if tableIndex < 0 || tableIndex >= len(schema.Tables) {
|
|
return false
|
|
}
|
|
|
|
table := schema.Tables[tableIndex]
|
|
if table.Relationships == nil {
|
|
return false
|
|
}
|
|
|
|
// Delete old entry if name changed
|
|
if oldName != rel.Name {
|
|
delete(table.Relationships, oldName)
|
|
}
|
|
|
|
table.Relationships[rel.Name] = rel
|
|
table.UpdateDate()
|
|
return true
|
|
}
|
|
|
|
// DeleteRelationship removes a relationship from a table
|
|
func (se *SchemaEditor) DeleteRelationship(schemaIndex, tableIndex int, relName string) bool {
|
|
if schemaIndex < 0 || schemaIndex >= len(se.db.Schemas) {
|
|
return false
|
|
}
|
|
|
|
schema := se.db.Schemas[schemaIndex]
|
|
if tableIndex < 0 || tableIndex >= len(schema.Tables) {
|
|
return false
|
|
}
|
|
|
|
table := schema.Tables[tableIndex]
|
|
if table.Relationships == nil {
|
|
return false
|
|
}
|
|
|
|
delete(table.Relationships, relName)
|
|
table.UpdateDate()
|
|
return true
|
|
}
|
|
|
|
// GetRelationship returns a relationship by name
|
|
func (se *SchemaEditor) GetRelationship(schemaIndex, tableIndex int, relName string) *models.Relationship {
|
|
if schemaIndex < 0 || schemaIndex >= len(se.db.Schemas) {
|
|
return nil
|
|
}
|
|
|
|
schema := se.db.Schemas[schemaIndex]
|
|
if tableIndex < 0 || tableIndex >= len(schema.Tables) {
|
|
return nil
|
|
}
|
|
|
|
table := schema.Tables[tableIndex]
|
|
if table.Relationships == nil {
|
|
return nil
|
|
}
|
|
|
|
return table.Relationships[relName]
|
|
}
|
|
|
|
// GetRelationshipNames returns all relationship names for a table
|
|
func (se *SchemaEditor) GetRelationshipNames(schemaIndex, tableIndex int) []string {
|
|
if schemaIndex < 0 || schemaIndex >= len(se.db.Schemas) {
|
|
return nil
|
|
}
|
|
|
|
schema := se.db.Schemas[schemaIndex]
|
|
if tableIndex < 0 || tableIndex >= len(schema.Tables) {
|
|
return nil
|
|
}
|
|
|
|
table := schema.Tables[tableIndex]
|
|
if table.Relationships == nil {
|
|
return nil
|
|
}
|
|
|
|
names := make([]string, 0, len(table.Relationships))
|
|
for name := range table.Relationships {
|
|
names = append(names, name)
|
|
}
|
|
sort.Strings(names)
|
|
return names
|
|
}
|