feat(writer): 🎉 Improve primary key handling by checking for explicit constraints and columns

This commit is contained in:
2026-01-28 22:08:27 +02:00
parent 91b6046b9b
commit 4ef7873c21
2 changed files with 92 additions and 14 deletions

View File

@@ -427,9 +427,11 @@ func (w *MigrationWriter) generateIndexScripts(model *models.Schema, current *mo
for _, modelTable := range model.Tables {
currentTable := currentTables[strings.ToLower(modelTable.Name)]
// Process primary keys first
// Process primary keys first - check explicit constraints
foundExplicitPK := false
for constraintName, constraint := range modelTable.Constraints {
if constraint.Type == models.PrimaryKeyConstraint {
foundExplicitPK = true
shouldCreate := true
if currentTable != nil {
@@ -464,6 +466,53 @@ func (w *MigrationWriter) generateIndexScripts(model *models.Schema, current *mo
}
}
// If no explicit PK constraint, check for columns with IsPrimaryKey = true
if !foundExplicitPK {
pkColumns := []string{}
for _, col := range modelTable.Columns {
if col.IsPrimaryKey {
pkColumns = append(pkColumns, col.SQLName())
}
}
if len(pkColumns) > 0 {
sort.Strings(pkColumns)
constraintName := fmt.Sprintf("pk_%s_%s", strings.ToLower(model.Name), strings.ToLower(modelTable.Name))
shouldCreate := true
if currentTable != nil {
// Check if a PK constraint already exists (by any name)
for _, constraint := range currentTable.Constraints {
if constraint.Type == models.PrimaryKeyConstraint {
shouldCreate = false
break
}
}
}
if shouldCreate {
sql, err := w.executor.ExecuteCreatePrimaryKey(CreatePrimaryKeyData{
SchemaName: model.Name,
TableName: modelTable.Name,
ConstraintName: constraintName,
Columns: strings.Join(pkColumns, ", "),
})
if err != nil {
return nil, err
}
script := MigrationScript{
ObjectName: fmt.Sprintf("%s.%s.%s", model.Name, modelTable.Name, constraintName),
ObjectType: "create primary key",
Schema: model.Name,
Priority: 160,
Sequence: len(scripts),
Body: sql,
}
scripts = append(scripts, script)
}
}
}
// Process indexes
for indexName, modelIndex := range modelTable.Indexes {
// Skip primary key indexes

View File

@@ -127,13 +127,35 @@ func (w *Writer) GenerateSchemaStatements(schema *models.Schema) ([]string, erro
// Phase 4: Primary keys
for _, table := range schema.Tables {
// First check for explicit PrimaryKeyConstraint
var pkConstraint *models.Constraint
for _, constraint := range table.Constraints {
if constraint.Type != models.PrimaryKeyConstraint {
continue
if constraint.Type == models.PrimaryKeyConstraint {
pkConstraint = constraint
break
}
}
if pkConstraint != nil {
stmt := fmt.Sprintf("ALTER TABLE %s.%s ADD CONSTRAINT %s PRIMARY KEY (%s)",
schema.SQLName(), table.SQLName(), constraint.Name, strings.Join(constraint.Columns, ", "))
schema.SQLName(), table.SQLName(), pkConstraint.Name, strings.Join(pkConstraint.Columns, ", "))
statements = append(statements, stmt)
} else {
// No explicit constraint, check for columns with IsPrimaryKey = true
pkColumns := []string{}
for _, col := range table.Columns {
if col.IsPrimaryKey {
pkColumns = append(pkColumns, col.SQLName())
}
}
if len(pkColumns) > 0 {
// Sort for consistent output
sort.Strings(pkColumns)
pkName := fmt.Sprintf("pk_%s_%s", schema.SQLName(), table.SQLName())
stmt := fmt.Sprintf("ALTER TABLE %s.%s ADD CONSTRAINT %s PRIMARY KEY (%s)",
schema.SQLName(), table.SQLName(), pkName, strings.Join(pkColumns, ", "))
statements = append(statements, stmt)
}
}
}
@@ -458,20 +480,27 @@ func (w *Writer) writePrimaryKeys(schema *models.Schema) error {
}
}
if pkConstraint == nil {
// No explicit PK constraint, skip
continue
}
var columnNames []string
pkName := fmt.Sprintf("pk_%s_%s", schema.SQLName(), table.SQLName())
// Build column list
columnNames := make([]string, 0, len(pkConstraint.Columns))
if pkConstraint != nil {
// Build column list from explicit constraint
columnNames = make([]string, 0, len(pkConstraint.Columns))
for _, colName := range pkConstraint.Columns {
if col, ok := table.Columns[colName]; ok {
columnNames = append(columnNames, col.SQLName())
}
}
} else {
// No explicit PK constraint, check for columns with IsPrimaryKey = true
for _, col := range table.Columns {
if col.IsPrimaryKey {
columnNames = append(columnNames, col.SQLName())
}
}
// Sort for consistent output
sort.Strings(columnNames)
}
if len(columnNames) == 0 {
continue