diff --git a/migrate.go b/migrate.go index de92847..def31ab 100644 --- a/migrate.go +++ b/migrate.go @@ -2,6 +2,7 @@ package go_sql_schema_migrate import ( "context" + "embed" "fmt" "os" "path/filepath" @@ -509,7 +510,7 @@ func parseAlterTableAddConstraint(schema *Schema, stmt string) { } } -func parseSchemaFile(schema *Schema, sql string) { +func ParseSchemaFile(schema *Schema, sql string) { // Split into statements statements := strings.Split(sql, ";") @@ -548,7 +549,7 @@ func parseSchemaFile(schema *Schema, sql string) { } } -func loadSchemaFiles(dir string) ([]SchemaFile, error) { +func LoadSchemaFiles(dir string) ([]SchemaFile, error) { files, err := os.ReadDir(dir) if err != nil { return nil, err @@ -576,8 +577,8 @@ func loadSchemaFiles(dir string) ([]SchemaFile, error) { return schemaFiles, nil } -func loadDesiredSchema(dir string) (*Schema, error) { - files, err := loadSchemaFiles(dir) +func LoadDesiredSchema(dir string) (*Schema, error) { + files, err := LoadSchemaFiles(dir) if err != nil { return nil, err } @@ -588,7 +589,7 @@ func loadDesiredSchema(dir string) (*Schema, error) { } for _, f := range files { - parseSchemaFile(schema, f.SQL) + ParseSchemaFile(schema, f.SQL) } return schema, nil @@ -981,11 +982,6 @@ func parseForeignKey(def string) *ForeignKey { return fk } -// LoadDesiredSchema loads schema definitions from SQL files in the given directory -func LoadDesiredSchema(dir string) (*Schema, error) { - return loadDesiredSchema(dir) -} - // GetMigrations compares the current database schema with the desired schema // and returns a list of SQL migration statements func GetMigrations(ctx context.Context, db *pgxpool.Pool, schemaDir string) ([]string, error) { @@ -1004,3 +1000,67 @@ func GetMigrations(ctx context.Context, db *pgxpool.Pool, schemaDir string) ([]s // Compare and generate migration SQL return CompareSchemas(currentSchema, desiredSchema), nil } + +func LoadSchemaFilesEmbed(dir string, fs embed.FS) ([]SchemaFile, error) { + files, err := fs.ReadDir(dir) + if err != nil { + return nil, err + } + + var schemaFiles []SchemaFile + for _, f := range files { + if !f.IsDir() && strings.HasSuffix(f.Name(), ".sql") { + content, err := fs.ReadFile(filepath.Join(dir, f.Name())) + if err != nil { + return nil, err + } + schemaFiles = append(schemaFiles, SchemaFile{ + Name: f.Name(), + SQL: string(content), + }) + } + } + + // Sort by filename (natural sort for numbered files) + sort.Slice(schemaFiles, func(i, j int) bool { + return schemaFiles[i].Name < schemaFiles[j].Name + }) + + return schemaFiles, nil +} +func LoadDesiredSchemaEmbed(dir string, fs embed.FS) (*Schema, error) { + files, err := LoadSchemaFilesEmbed(dir, fs) + if err != nil { + return nil, err + } + + schema := &Schema{ + Types: make(map[string]string), + Tables: make(map[string]*Table), + } + + for _, f := range files { + ParseSchemaFile(schema, f.SQL) + } + + return schema, nil +} + +// GetMigrationsEmbed compares the current database schema with the desired schema +// and returns a list of SQL migration statements +func GetMigrationsEmbed(ctx context.Context, db *pgxpool.Pool, schemaDir string, fs embed.FS) ([]string, error) { + // Load current database schema + currentSchema, err := GetCurrentSchema(ctx, db) + if err != nil { + return nil, fmt.Errorf("failed to get current schema: %w", err) + } + + // Load desired schema from files + desiredSchema, err := LoadDesiredSchemaEmbed(schemaDir, fs) + if err != nil { + return nil, fmt.Errorf("failed to load desired schema: %w", err) + } + + // Compare and generate migration SQL + return CompareSchemas(currentSchema, desiredSchema), nil +}