From 926cead7859b38c0429bdf8e50a178ee0149e9c7 Mon Sep 17 00:00:00 2001 From: Alexis Viscogliosi Date: Thu, 31 Oct 2024 09:58:51 +0100 Subject: [PATCH] feature: raw sql possible --- cmd/create.go | 18 +++++-- docs/docs/03-cli/03-create.md | 13 +++++- example/sqlite/migrations/migrations.go | 8 ++++ go.mod | 2 +- go.sum | 3 ++ go.work.sum | 1 + pkg/amigo/amigo.go | 60 ++++++++++++++++++------ pkg/amigo/run_migration.go | 15 ++++-- pkg/amigoctx/ctx.go | 39 +++++++++++++--- pkg/schema/base/base.go | 10 +++- pkg/schema/schema.go | 2 + pkg/schema/sql_migration_impl.go | 62 +++++++++++++++++++++++++ pkg/templates/migration.sql.tmpl | 3 ++ pkg/templates/migrations.go.tmpl | 7 ++- pkg/templates/types.go | 6 ++- pkg/templates/util.go | 6 +++ pkg/types/types.go | 12 +++++ pkg/utils/mig.go | 11 +++-- 18 files changed, 237 insertions(+), 41 deletions(-) create mode 100644 pkg/schema/sql_migration_impl.go create mode 100644 pkg/templates/migration.sql.tmpl diff --git a/cmd/create.go b/cmd/create.go index 173fc63..9687021 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -2,6 +2,10 @@ package cmd import ( "fmt" + "path" + "path/filepath" + "time" + "github.com/alexisvisco/amigo/pkg/amigo" "github.com/alexisvisco/amigo/pkg/types" "github.com/alexisvisco/amigo/pkg/utils" @@ -9,9 +13,6 @@ import ( "github.com/alexisvisco/amigo/pkg/utils/logger" "github.com/gobuffalo/flect" "github.com/spf13/cobra" - "path" - "path/filepath" - "time" ) // createCmd represents the create command @@ -48,7 +49,11 @@ var createCmd = &cobra.Command{ version := now.UTC().Format(utils.FormatTime) cmdCtx.Create.Version = version - migrationFileName := fmt.Sprintf("%s_%s.go", version, flect.Underscore(args[0])) + ext := "go" + if cmdCtx.Create.Type == "sql" { + ext = "sql" + } + migrationFileName := fmt.Sprintf("%s_%s.%s", version, flect.Underscore(args[0]), ext) file, err := utils.CreateOrOpenFile(filepath.Join(cmdCtx.MigrationFolder, migrationFileName)) if err != nil { return fmt.Errorf("unable to open/create file: %w", err) @@ -97,7 +102,7 @@ var createCmd = &cobra.Command{ func init() { rootCmd.AddCommand(createCmd) createCmd.Flags().StringVar(&cmdCtx.Create.Type, "type", "change", - "The type of migration to create, possible values are [classic, change]") + "The type of migration to create, possible values are [classic, change, sql]") createCmd.Flags().BoolVarP(&cmdCtx.Create.Dump, "dump", "d", false, "dump with pg_dump the current schema and add it to the current migration") @@ -105,6 +110,9 @@ func init() { createCmd.Flags().StringVarP(&cmdCtx.Create.DumpSchema, "dump-schema", "s", "public", "the schema to dump if --dump is set") + createCmd.Flags().StringVar(&cmdCtx.Create.SQLSeparator, "sql-separator", "-- migrate:down", + "the separator to split the up and down part of the migration") + createCmd.Flags().BoolVar(&cmdCtx.Create.Skip, "skip", false, "skip will set the migration as applied without executing it") } diff --git a/docs/docs/03-cli/03-create.md b/docs/docs/03-cli/03-create.md index e80beb3..e1b2e5b 100644 --- a/docs/docs/03-cli/03-create.md +++ b/docs/docs/03-cli/03-create.md @@ -50,7 +50,7 @@ func (m Migration20240502155033SchemaVersion) Date() time.Time { - `--skip` will insert the current version of the schema into the `mig_schema_versions` table without running the migration (because the schema already exists). - `--dump-schema` to specify the schema to dump. (default is `public`) - `--pg-dump-path` to specify the path to the `pg_dump` command. -- `--type` to specify the type of migration to create, possible values are [classic, change] (default is `change`) +- `--type` to specify the type of migration to create, possible values are [classic, change, sql] (default is `change`) ## Difference between classic and change migration @@ -109,7 +109,18 @@ func (m Migration20240502155033SchemaVersion) Change(s *pg.Schema) { } ``` +### Raw sql migrations +You can also create a raw SQL migration by using the `--type sql` flag. + +This will produce a migration file like this: + +```sql +-- todo: write up migrations here +-- migrate:down +-- todo: write down migrations here + +``` diff --git a/example/sqlite/migrations/migrations.go b/example/sqlite/migrations/migrations.go index b5b437d..36c0ea6 100644 --- a/example/sqlite/migrations/migrations.go +++ b/example/sqlite/migrations/migrations.go @@ -4,10 +4,18 @@ package migrations import ( "github.com/alexisvisco/amigo/pkg/schema" + "github.com/alexisvisco/amigo/pkg/schema/pg" + + "embed" ) +//go:embed *.sql +var sqlMigrationsFS embed.FS + var Migrations = []schema.Migration{ &Migration20240602080728CreateTableSchemaVersion{}, &Migration20240602081304AddIndex{}, &Migration20240602081806DropIndex{}, + schema.NewSQLMigration[*pg.Schema](sqlMigrationsFS, "20240602081806_drop_index.sql", "2024-06-02T10:18:06+02:00", + "-- migrate:down"), } diff --git a/go.mod b/go.mod index d8de33d..d920fad 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/simukti/sqldb-logger v0.0.0-20230108155151-646c1a075551 // user for the cli (only imported in cmd) - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 ) diff --git a/go.sum b/go.sum index f2ab859..1c71c54 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,7 @@ github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4E github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -70,6 +71,8 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= diff --git a/go.work.sum b/go.work.sum index cef2d68..27181f5 100644 --- a/go.work.sum +++ b/go.work.sum @@ -27,6 +27,7 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= diff --git a/pkg/amigo/amigo.go b/pkg/amigo/amigo.go index e4d01d7..2de75be 100644 --- a/pkg/amigo/amigo.go +++ b/pkg/amigo/amigo.go @@ -3,13 +3,6 @@ package amigo import ( "database/sql" "fmt" - "github.com/alexisvisco/amigo/pkg/amigoctx" - "github.com/alexisvisco/amigo/pkg/schema" - "github.com/alexisvisco/amigo/pkg/templates" - "github.com/alexisvisco/amigo/pkg/types" - "github.com/alexisvisco/amigo/pkg/utils" - "github.com/alexisvisco/amigo/pkg/utils/cmdexec" - "github.com/gobuffalo/flect" "io" "os" "path" @@ -18,6 +11,14 @@ import ( "sort" "strings" "time" + + "github.com/alexisvisco/amigo/pkg/amigoctx" + "github.com/alexisvisco/amigo/pkg/schema" + "github.com/alexisvisco/amigo/pkg/templates" + "github.com/alexisvisco/amigo/pkg/types" + "github.com/alexisvisco/amigo/pkg/utils" + "github.com/alexisvisco/amigo/pkg/utils/cmdexec" + "github.com/gobuffalo/flect" ) type Amigo struct { @@ -128,6 +129,7 @@ type GenerateMigrationFileParams struct { // GenerateMigrationFile generate a migration file in the migrations folder func (a Amigo) GenerateMigrationFile(params *GenerateMigrationFileParams) error { + structName := utils.MigrationStructName(params.Now, params.Name) orDefault := func(s string) string { @@ -138,6 +140,7 @@ func (a Amigo) GenerateMigrationFile(params *GenerateMigrationFileParams) error } fileContent, err := templates.GetMigrationTemplate(templates.MigrationData{ + IsSQL: params.Type == types.MigrationFileTypeSQL, Package: a.ctx.PackagePath, StructName: structName, Name: flect.Underscore(params.Name), @@ -173,13 +176,33 @@ func (a Amigo) GenerateMigrationsFiles(writer io.Writer) error { } var migrations []string + var mustImportSchemaPackage *string for _, k := range keys { - migrations = append(migrations, utils.MigrationStructName(k, migrationFiles[k])) + if migrationFiles[k].IsSQL { + // schema.NewSQLMigration[*pg.Schema](sqlMigrationsFS, "20240602081806_drop_index.sql", "2024-06-02T10:18:06+02:00", "---- down:"), + line := fmt.Sprintf("schema.NewSQLMigration[%s](sqlMigrationsFS, \"%s\", \"%s\", \"%s\")", + a.Driver.StructName(), + migrationFiles[k].FulName, + k.Format(time.RFC3339), + a.ctx.Create.SQLSeparator, + ) + + migrations = append(migrations, line) + + if mustImportSchemaPackage == nil { + v := a.Driver.PackageSchemaPath() + mustImportSchemaPackage = &v + } + } else { + migrations = append(migrations, fmt.Sprintf("&%s{}", utils.MigrationStructName(k, migrationFiles[k].Name))) + + } } content, err := templates.GetMigrationsTemplate(templates.MigrationsData{ - Package: a.ctx.PackagePath, - Migrations: migrations, + Package: a.ctx.PackagePath, + Migrations: migrations, + ImportSchemaPackage: mustImportSchemaPackage, }) if err != nil { @@ -214,8 +237,14 @@ func (a Amigo) GetStatus(db *sql.DB) ([]string, error) { return state, nil } -func (a Amigo) GetMigrationFiles(ascending bool) (map[time.Time]string, []time.Time, error) { - migrationFiles := make(map[time.Time]string) +type MigrationFile struct { + Name string + FulName string + IsSQL bool +} + +func (a Amigo) GetMigrationFiles(ascending bool) (map[time.Time]MigrationFile, []time.Time, error) { + migrationFiles := make(map[time.Time]MigrationFile) // get the list of structs by the file name err := filepath.Walk(a.ctx.MigrationFolder, func(path string, info os.FileInfo, err error) error { @@ -224,13 +253,14 @@ func (a Amigo) GetMigrationFiles(ascending bool) (map[time.Time]string, []time.T } if !info.IsDir() { - if utils.FileRegexp.MatchString(info.Name()) { - matches := utils.FileRegexp.FindStringSubmatch(info.Name()) + if utils.MigrationFileRegexp.MatchString(info.Name()) { + matches := utils.MigrationFileRegexp.FindStringSubmatch(info.Name()) fileTime := matches[1] migrationName := matches[2] + ext := matches[3] t, _ := time.Parse(utils.FormatTime, fileTime) - migrationFiles[t] = migrationName + migrationFiles[t] = MigrationFile{Name: migrationName, IsSQL: ext == "sql", FulName: info.Name()} } } diff --git a/pkg/amigo/run_migration.go b/pkg/amigo/run_migration.go index 017e0a3..13bee53 100644 --- a/pkg/amigo/run_migration.go +++ b/pkg/amigo/run_migration.go @@ -4,6 +4,10 @@ import ( "context" "database/sql" "errors" + "io" + "log/slog" + "time" + "github.com/alexisvisco/amigo/pkg/amigoctx" "github.com/alexisvisco/amigo/pkg/schema" "github.com/alexisvisco/amigo/pkg/schema/base" @@ -13,9 +17,6 @@ import ( "github.com/alexisvisco/amigo/pkg/utils" "github.com/alexisvisco/amigo/pkg/utils/dblog" sqldblogger "github.com/simukti/sqldb-logger" - "io" - "log/slog" - "time" ) var ( @@ -32,6 +33,7 @@ type RunMigrationParams struct { Direction types.MigrationDirection Migrations []schema.Migration LogOutput io.Writer + Context context.Context } // RunMigrations migrates the database, it is launched via the generated main file or manually in a codebase. @@ -41,7 +43,12 @@ func (a Amigo) RunMigrations(params RunMigrationParams) error { return err } - ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(a.ctx.Migration.Timeout)) + originCtx := context.Background() + if params.Context != nil { + originCtx = params.Context + } + + ctx, cancel := context.WithDeadline(originCtx, time.Now().Add(a.ctx.Migration.Timeout)) defer cancel() oldLogger := slog.Default() diff --git a/pkg/amigoctx/ctx.go b/pkg/amigoctx/ctx.go index 3e601d5..b89bb5a 100644 --- a/pkg/amigoctx/ctx.go +++ b/pkg/amigoctx/ctx.go @@ -3,10 +3,11 @@ package amigoctx import ( "errors" "fmt" - "github.com/alexisvisco/amigo/pkg/types" "regexp" "strings" "time" + + "github.com/alexisvisco/amigo/pkg/types" ) var ( @@ -71,6 +72,26 @@ func (r *Context) GetRealDSN() string { return r.Root.DSN } +func (a *Context) WithAmigoFolder(folder string) *Context { + a.Root.AmigoFolderPath = folder + return a +} + +func (a *Context) WithMigrationFolder(folder string) *Context { + a.Root.MigrationFolder = folder + return a +} + +func (a *Context) WithPackagePath(packagePath string) *Context { + a.Root.PackagePath = packagePath + return a +} + +func (a *Context) WithSchemaVersionTable(table string) *Context { + a.Root.SchemaVersionTable = table + return a +} + func (a *Context) WithDSN(dsn string) *Context { a.Root.DSN = dsn return a @@ -86,6 +107,11 @@ func (a *Context) WithSteps(steps int) *Context { return a } +func (a *Context) WithShowSQL(showSQL bool) *Context { + a.Root.ShowSQL = showSQL + return a +} + func (r *Root) ValidateDSN() error { if r.DSN == "" { return ErrDSNEmpty @@ -116,17 +142,18 @@ func (m *Migration) ValidateVersion() error { } type Create struct { - Type string - Dump bool - DumpSchema string - Skip bool + Type string + Dump bool + DumpSchema string + SQLSeparator string + Skip bool // Version is post setted after the name have been generated from the arg and time Version string } func (c *Create) ValidateType() error { - allowedTypes := []string{string(types.MigrationFileTypeClassic), string(types.MigrationFileTypeChange)} + allowedTypes := []string{string(types.MigrationFileTypeClassic), string(types.MigrationFileTypeChange), string(types.MigrationFileTypeSQL)} for _, t := range allowedTypes { if c.Type == t { diff --git a/pkg/schema/base/base.go b/pkg/schema/base/base.go index dfd989b..adb853f 100644 --- a/pkg/schema/base/base.go +++ b/pkg/schema/base/base.go @@ -2,10 +2,11 @@ package base import ( "fmt" + "strings" + "github.com/alexisvisco/amigo/pkg/schema" "github.com/alexisvisco/amigo/pkg/types" "github.com/alexisvisco/amigo/pkg/utils" - "strings" ) // Schema is the base schema. It is used to support unknown database types and provide a default implementation. @@ -117,6 +118,13 @@ func (p *Schema) FindAppliedVersions() []string { return versions } +func (p *Schema) Exec(query string, args ...interface{}) { + _, err := p.TX.ExecContext(p.Context.Context, query, args...) + if err != nil { + p.Context.RaiseError(fmt.Errorf("error while executing query: %w", err)) + } +} + func ColumnType(ctx *schema.MigratorContext, options schema.ColumnData) func() string { return func() string { strBuilder := strings.Builder{} diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go index 9d8522b..5e2e62d 100644 --- a/pkg/schema/schema.go +++ b/pkg/schema/schema.go @@ -5,4 +5,6 @@ type Schema interface { AddVersion(version string) RemoveVersion(version string) FindAppliedVersions() []string + + Exec(query string, args ...interface{}) } diff --git a/pkg/schema/sql_migration_impl.go b/pkg/schema/sql_migration_impl.go new file mode 100644 index 0000000..e2b4964 --- /dev/null +++ b/pkg/schema/sql_migration_impl.go @@ -0,0 +1,62 @@ +package schema + +import ( + "bytes" + "embed" + "fmt" + "time" +) + +type SQLMigration[T Schema] struct { + fs embed.FS + name string + time string // RFC3339 + delimiter string +} + +func NewSQLMigration[T Schema](fs embed.FS, name string, time string, delimiter string) SQLMigration[T] { + return SQLMigration[T]{fs: fs, name: name, time: time, delimiter: delimiter} +} + +func (s SQLMigration[T]) Up(x T) { + up, _, err := s.parseContent() + + if err != nil { + panic(err) + } + + x.Exec(up) +} + +func (s SQLMigration[T]) Down(x T) { + _, down, err := s.parseContent() + + if err != nil { + panic(err) + } + + x.Exec(down) +} + +func (s SQLMigration[T]) Name() string { + return s.name +} + +func (s SQLMigration[T]) Date() time.Time { + t, _ := time.Parse(time.RFC3339, s.time) + return t +} + +func (s SQLMigration[T]) parseContent() (string, string, error) { + file, err := s.fs.ReadFile(s.name) + if err != nil { + return "", "", fmt.Errorf("unable to read file %s: %w", s.name, err) + } + + split := bytes.Split(file, []byte(s.delimiter)) + if len(split) != 2 { + return "", "", fmt.Errorf("invalid content, expected 2 parts, got %d", len(split)) + } + + return string(split[0]), string(split[1]), nil +} diff --git a/pkg/templates/migration.sql.tmpl b/pkg/templates/migration.sql.tmpl new file mode 100644 index 0000000..f971661 --- /dev/null +++ b/pkg/templates/migration.sql.tmpl @@ -0,0 +1,3 @@ +-- todo: write up migrations here +-- migrate:down +-- todo: write down migrations here diff --git a/pkg/templates/migrations.go.tmpl b/pkg/templates/migrations.go.tmpl index 3a6b032..4e02a5e 100644 --- a/pkg/templates/migrations.go.tmpl +++ b/pkg/templates/migrations.go.tmpl @@ -4,10 +4,15 @@ package {{ .Package }} import ( "github.com/alexisvisco/amigo/pkg/schema" + "embed" + {{if .ImportSchemaPackage}}"{{ .ImportSchemaPackage }}"{{end}} ) +//go:embed *.sql +var sqlMigrationsFS embed.FS + var Migrations = []schema.Migration{ {{- range .Migrations }} - &{{ . }}{}, + {{ . }}, {{- end }} } diff --git a/pkg/templates/types.go b/pkg/templates/types.go index caf1c5c..3e3aca4 100644 --- a/pkg/templates/types.go +++ b/pkg/templates/types.go @@ -4,11 +4,13 @@ import "github.com/alexisvisco/amigo/pkg/types" type ( MigrationsData struct { - Package string - Migrations []string + Package string + Migrations []string + ImportSchemaPackage *string } MigrationData struct { + IsSQL bool Package string StructName string Name string diff --git a/pkg/templates/util.go b/pkg/templates/util.go index 20aef38..9945977 100644 --- a/pkg/templates/util.go +++ b/pkg/templates/util.go @@ -14,6 +14,9 @@ var migrationsList string //go:embed migration.go.tmpl var migration string +//go:embed migration.sql.tmpl +var migrationSQL string + //go:embed init_create_table.go.tmpl var initCreateTable string @@ -38,6 +41,9 @@ func GetMigrationsTemplate(t MigrationsData) (string, error) { } func GetMigrationTemplate(t MigrationData) (string, error) { + if t.IsSQL { + return migrationSQL, nil + } t.Imports = append(t.Imports, "time") t.Imports = append(t.Imports, "github.com/alexisvisco/amigo/pkg/schema/"+t.PackageDriverName) diff --git a/pkg/types/types.go b/pkg/types/types.go index bcf728a..66d49e2 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -55,6 +55,17 @@ func (d Driver) PackageSchemaPath() string { } } +func (d Driver) StructName() string { + switch d { + case DriverPostgres: + return "*pg.Schema" + case DriverSQLite: + return "*sqlite.Schema" + default: + return "*base.Schema" + } +} + func GetDriver(dsn string) Driver { switch { case strings.HasPrefix(dsn, "postgres"): @@ -97,6 +108,7 @@ type MigrationFileType string const ( MigrationFileTypeChange MigrationFileType = "change" MigrationFileTypeClassic MigrationFileType = "classic" + MigrationFileTypeSQL MigrationFileType = "sql" ) var MigrationFileTypeValues = []MigrationFileType{ diff --git a/pkg/utils/mig.go b/pkg/utils/mig.go index 068fe84..145f820 100644 --- a/pkg/utils/mig.go +++ b/pkg/utils/mig.go @@ -3,10 +3,11 @@ package utils import ( "errors" "fmt" - "github.com/gobuffalo/flect" "regexp" "strings" "time" + + "github.com/gobuffalo/flect" ) func ParseMigrationVersion(f string) (string, error) { @@ -14,15 +15,15 @@ func ParseMigrationVersion(f string) (string, error) { return f, nil } - if FileRegexp.MatchString(f) { + if MigrationFileRegexp.MatchString(f) { // get the prefix and remove underscore - return strings.ReplaceAll(FileRegexp.FindStringSubmatch(f)[1], "_", ""), nil + return strings.ReplaceAll(MigrationFileRegexp.FindStringSubmatch(f)[1], "_", ""), nil } - return "", errors.New("invalid version format, should be of form: 20060102150405_migration_name.go, 20060102150405") + return "", errors.New("invalid version format, should be of form: 20060102150405_migration_name.{go,sql}, 20060102150405") } -var FileRegexp = regexp.MustCompile(`(\d{14})_(.*)\.go`) +var MigrationFileRegexp = regexp.MustCompile(`(\d{14})_(.*)\.(go|sql)`) var TimeRegexp = regexp.MustCompile(`\d{14}`) const FormatTime = "20060102150405"