feat(writers): stamp RelSpec version in generated headers; preserve DBML column order
- Add pkg/buildinfo with Version/BuildDate (set via ldflags, VCS fallback); cmd/relspec now sources version info from it - Emit "RelSpec <version> (built: <date>)" in generated file headers for bun, gorm, drizzle, pgsql (incl. migration), mssql, sqlite writers - pgsql writer: getSortedColumns now sorts by Sequence then Name so the streaming WriteSchema/WriteDatabase path preserves source column order - dbml reader: mergeTable re-bases merged-in column Sequence values past the existing max, fixing colliding sequences (and alphabetical fallback) when a table is split across multiple DBML files - Tests for bun/gorm header + column order, and dbml multi-file merge ordering
This commit is contained in:
@@ -112,6 +112,46 @@ func TestWriter_WriteTable_MultilineDescriptionProducesValidGo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriter_WriteTable_ColumnOrderFollowsSequence(t *testing.T) {
|
||||
// Column.Sequence carries the source (e.g. DBML) declaration order; the
|
||||
// generated struct fields must follow it, not fall back to alphabetical.
|
||||
table := models.InitTable("widget", "public")
|
||||
table.Columns["zeta"] = &models.Column{Name: "zeta", Type: "varchar", Length: 50, Sequence: 1}
|
||||
table.Columns["alpha"] = &models.Column{Name: "alpha", Type: "bigint", NotNull: true, IsPrimaryKey: true, AutoIncrement: true, Sequence: 2}
|
||||
table.Columns["mid_field"] = &models.Column{Name: "mid_field", Type: "integer", Sequence: 3}
|
||||
table.Columns["beta"] = &models.Column{Name: "beta", Type: "varchar", Length: 100, Sequence: 4}
|
||||
|
||||
outputPath := filepath.Join(t.TempDir(), "widget.go")
|
||||
writer := NewWriter(&writers.WriterOptions{OutputPath: outputPath, PackageName: "models"})
|
||||
if err := writer.WriteTable(table); err != nil {
|
||||
t.Fatalf("WriteTable() error = %v", err)
|
||||
}
|
||||
|
||||
generated, err := os.ReadFile(outputPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read generated code: %v", err)
|
||||
}
|
||||
src := string(generated)
|
||||
if _, err := parser.ParseFile(token.NewFileSet(), outputPath, generated, parser.AllErrors); err != nil {
|
||||
t.Fatalf("generated code is invalid Go: %v\n%s", err, src)
|
||||
}
|
||||
|
||||
positions := make([]int, 0, 4)
|
||||
for _, field := range []string{"Zeta ", "Alpha ", "MidField ", "Beta "} {
|
||||
idx := strings.Index(src, "\t"+field)
|
||||
if idx < 0 {
|
||||
t.Fatalf("field %q missing from generated struct:\n%s", field, src)
|
||||
}
|
||||
positions = append(positions, idx)
|
||||
}
|
||||
for i := 1; i < len(positions); i++ {
|
||||
if positions[i] <= positions[i-1] {
|
||||
t.Errorf("struct fields not in Sequence order (want zeta, alpha, mid_field, beta):\n%s", src)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriter_WriteDatabase_MultiFile(t *testing.T) {
|
||||
// Create a database with two tables
|
||||
db := models.InitDatabase("testdb")
|
||||
|
||||
Reference in New Issue
Block a user