fix: writer/reader correctness and determinism issues
- merge: cloneTable keeps relationships; skip-tables applies to new schemas - diff: detect schema description/owner changes - prisma: reader no longer turns relation fields into columns, enum detection via declared names; writer type mapping is ordered - typeorm writer: keep explicit SQL types that cannot be inferred - drizzle: enum columns call the enum constant; reader resolves them - mysql/mssql/sqlite writers: honour OutputPath, deterministic column and constraint order; mssql live execute covers full schema - template: ToYAML recovers from panics; Merge nil-pointer loop - regenerate drizzle fixtures
This commit is contained in:
+49
-16
@@ -29,18 +29,11 @@ func (w *Writer) WriteDatabase(db *models.Database) error {
|
||||
if conn, ok := w.options.Metadata["connection_string"].(string); ok && conn != "" {
|
||||
return w.execute(db, conn)
|
||||
}
|
||||
if w.writer == nil {
|
||||
if w.options.OutputPath != "" {
|
||||
f, err := os.Create(w.options.OutputPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
w.writer = f
|
||||
} else {
|
||||
w.writer = os.Stdout
|
||||
}
|
||||
release, err := w.openOutput()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer release()
|
||||
return w.writeDatabaseDDL(db)
|
||||
}
|
||||
|
||||
@@ -56,7 +49,33 @@ func (w *Writer) writeDatabaseDDL(db *models.Database) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// openOutput points w.writer at the configured destination (output file or
|
||||
// stdout) when none is set, and returns a func that releases it again.
|
||||
func (w *Writer) openOutput() (func(), error) {
|
||||
if w.writer != nil {
|
||||
return func() {}, nil
|
||||
}
|
||||
if w.options != nil && w.options.OutputPath != "" {
|
||||
f, err := os.Create(w.options.OutputPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w.writer = f
|
||||
return func() {
|
||||
f.Close()
|
||||
w.writer = nil
|
||||
}, nil
|
||||
}
|
||||
w.writer = os.Stdout
|
||||
return func() { w.writer = nil }, nil
|
||||
}
|
||||
|
||||
func (w *Writer) WriteSchema(s *models.Schema) error {
|
||||
release, err := w.openOutput()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer release()
|
||||
for _, t := range s.Tables {
|
||||
if err := w.writeTable(s, t); err != nil {
|
||||
return err
|
||||
@@ -66,9 +85,11 @@ func (w *Writer) WriteSchema(s *models.Schema) error {
|
||||
}
|
||||
|
||||
func (w *Writer) WriteTable(t *models.Table) error {
|
||||
if w.writer == nil {
|
||||
w.writer = os.Stdout
|
||||
release, err := w.openOutput()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer release()
|
||||
return w.writeTable(nil, t)
|
||||
}
|
||||
|
||||
@@ -83,7 +104,12 @@ func (w *Writer) writeTable(s *models.Schema, t *models.Table) error {
|
||||
for _, c := range t.Columns {
|
||||
cols = append(cols, c)
|
||||
}
|
||||
sort.Slice(cols, func(i, j int) bool { return cols[i].Sequence < cols[j].Sequence })
|
||||
sort.Slice(cols, func(i, j int) bool {
|
||||
if cols[i].Sequence != cols[j].Sequence {
|
||||
return cols[i].Sequence < cols[j].Sequence
|
||||
}
|
||||
return cols[i].Name < cols[j].Name
|
||||
})
|
||||
defs := []string{}
|
||||
pk := []string{}
|
||||
for _, c := range cols {
|
||||
@@ -105,7 +131,13 @@ func (w *Writer) writeTable(s *models.Schema, t *models.Table) error {
|
||||
pk = append(pk, quote(c.Name))
|
||||
}
|
||||
}
|
||||
for _, c := range t.Constraints {
|
||||
constraintNames := make([]string, 0, len(t.Constraints))
|
||||
for name := range t.Constraints {
|
||||
constraintNames = append(constraintNames, name)
|
||||
}
|
||||
sort.Strings(constraintNames)
|
||||
for _, name := range constraintNames {
|
||||
c := t.Constraints[name]
|
||||
if c.Type == models.PrimaryKeyConstraint {
|
||||
pk = nil
|
||||
for _, n := range c.Columns {
|
||||
@@ -117,7 +149,8 @@ func (w *Writer) writeTable(s *models.Schema, t *models.Table) error {
|
||||
if len(pk) > 0 {
|
||||
defs = append(defs, " PRIMARY KEY ("+strings.Join(pk, ", ")+")")
|
||||
}
|
||||
for _, c := range t.Constraints {
|
||||
for _, name := range constraintNames {
|
||||
c := t.Constraints[name]
|
||||
if c.Type == models.UniqueConstraint {
|
||||
defs = append(defs, fmt.Sprintf(" CONSTRAINT %s UNIQUE (%s)", quote(c.Name), quoted(c.Columns)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user