diff --git a/database/console/driver/sqlite.go b/database/console/driver/sqlite.go deleted file mode 100644 index 63d704dbc..000000000 --- a/database/console/driver/sqlite.go +++ /dev/null @@ -1,276 +0,0 @@ -package driver - -import ( - "database/sql" - "fmt" - "io" - nurl "net/url" - "strconv" - "strings" - - _ "github.com/glebarez/go-sqlite" - "github.com/golang-migrate/migrate/v4" - "github.com/golang-migrate/migrate/v4/database" - "github.com/hashicorp/go-multierror" - "go.uber.org/atomic" -) - -func init() { - database.Register("sqlite", &Sqlite{}) -} - -var ( - DefaultMigrationsTable = "schema_migrations" - ErrNilConfig = fmt.Errorf("no config") -) - -type Config struct { - MigrationsTable string - DatabaseName string - NoTxWrap bool -} - -type Sqlite struct { - db *sql.DB - isLocked atomic.Bool - - config *Config -} - -func WithInstance(instance *sql.DB, config *Config) (database.Driver, error) { - if config == nil { - return nil, ErrNilConfig - } - - if err := instance.Ping(); err != nil { - return nil, err - } - - if len(config.MigrationsTable) == 0 { - config.MigrationsTable = DefaultMigrationsTable - } - - mx := &Sqlite{ - db: instance, - config: config, - } - if err := mx.ensureVersionTable(); err != nil { - return nil, err - } - return mx, nil -} - -// ensureVersionTable checks if versions table exists and, if not, creates it. -// Note that this function locks the database, which deviates from the usual -// convention of "caller locks" in the Sqlite type. -func (m *Sqlite) ensureVersionTable() (err error) { - if err = m.Lock(); err != nil { - return err - } - - defer func() { - if e := m.Unlock(); e != nil { - if err == nil { - err = e - } else { - err = multierror.Append(err, e) - } - } - }() - - query := fmt.Sprintf(` - CREATE TABLE IF NOT EXISTS %s (version uint64,dirty bool); - CREATE UNIQUE INDEX IF NOT EXISTS version_unique ON %s (version); - `, m.config.MigrationsTable, m.config.MigrationsTable) - - if _, err = m.db.Exec(query); err != nil { - return err - } - return nil -} - -func (m *Sqlite) Open(url string) (database.Driver, error) { - purl, err := nurl.Parse(url) - if err != nil { - return nil, err - } - dbfile := strings.Replace(migrate.FilterCustomQuery(purl).String(), "sqlite://", "", 1) - db, err := sql.Open("sqlite", dbfile) - if err != nil { - return nil, err - } - - qv := purl.Query() - - migrationsTable := qv.Get("x-migrations-table") - if len(migrationsTable) == 0 { - migrationsTable = DefaultMigrationsTable - } - - noTxWrap := false - if v := qv.Get("x-no-tx-wrap"); v != "" { - noTxWrap, err = strconv.ParseBool(v) - if err != nil { - return nil, fmt.Errorf("x-no-tx-wrap: %s", err) - } - } - - mx, err := WithInstance(db, &Config{ - DatabaseName: purl.Path, - MigrationsTable: migrationsTable, - NoTxWrap: noTxWrap, - }) - if err != nil { - return nil, err - } - return mx, nil -} - -func (m *Sqlite) Close() error { - return m.db.Close() -} - -func (m *Sqlite) Drop() (err error) { - query := `SELECT name FROM sqlite_master WHERE type = 'table';` - tables, err := m.db.Query(query) - if err != nil { - return &database.Error{OrigErr: err, Query: []byte(query)} - } - defer func() { - if errClose := tables.Close(); errClose != nil { - err = multierror.Append(err, errClose) - } - }() - - var tableNames []string - for tables.Next() { - var tableName string - if err = tables.Scan(&tableName); err != nil { - return err - } - if len(tableName) > 0 { - tableNames = append(tableNames, tableName) - } - } - if err = tables.Err(); err != nil { - return &database.Error{OrigErr: err, Query: []byte(query)} - } - - if len(tableNames) > 0 { - for _, t := range tableNames { - // SQLite has a sqlite_sequence table and it cannot be dropped - if t == "sqlite_sequence" { - _, err = m.db.Exec("DELETE FROM sqlite_sequence;") - if err != nil { - return &database.Error{OrigErr: err, Query: []byte("DELETE FROM sqlite_sequence;")} - } - - continue - } - - query = "DROP TABLE " + t - err = m.executeQuery(query) - if err != nil { - return &database.Error{OrigErr: err, Query: []byte(query)} - } - } - query = "VACUUM" - _, err = m.db.Exec(query) - if err != nil { - return &database.Error{OrigErr: err, Query: []byte(query)} - } - } - - return nil -} - -func (m *Sqlite) Lock() error { - if !m.isLocked.CompareAndSwap(false, true) { - return database.ErrLocked - } - return nil -} - -func (m *Sqlite) Unlock() error { - if !m.isLocked.CompareAndSwap(true, false) { - return database.ErrNotLocked - } - return nil -} - -func (m *Sqlite) Run(migration io.Reader) error { - migr, err := io.ReadAll(migration) - if err != nil { - return err - } - query := string(migr[:]) - - if m.config.NoTxWrap { - return m.executeQueryNoTx(query) - } - return m.executeQuery(query) -} - -func (m *Sqlite) executeQuery(query string) error { - tx, err := m.db.Begin() - if err != nil { - return &database.Error{OrigErr: err, Err: "transaction start failed"} - } - if _, err = tx.Exec(query); err != nil { - if errRollback := tx.Rollback(); errRollback != nil { - err = multierror.Append(err, errRollback) - } - return &database.Error{OrigErr: err, Query: []byte(query)} - } - if err = tx.Commit(); err != nil { - return &database.Error{OrigErr: err, Err: "transaction commit failed"} - } - return nil -} - -func (m *Sqlite) executeQueryNoTx(query string) error { - if _, err := m.db.Exec(query); err != nil { - return &database.Error{OrigErr: err, Query: []byte(query)} - } - return nil -} - -func (m *Sqlite) SetVersion(version int, dirty bool) error { - tx, err := m.db.Begin() - if err != nil { - return &database.Error{OrigErr: err, Err: "transaction start failed"} - } - - query := "DELETE FROM " + m.config.MigrationsTable - if _, err = tx.Exec(query); err != nil { - return &database.Error{OrigErr: err, Query: []byte(query)} - } - - // Also re-write the schema version for nil dirty versions to prevent - // empty schema version for failed down migration on the first migration - // See: https://github.com/golang-migrate/migrate/issues/330 - if version >= 0 || (version == database.NilVersion && dirty) { - query = fmt.Sprintf(`INSERT INTO %s (version, dirty) VALUES (?, ?)`, m.config.MigrationsTable) - if _, err = tx.Exec(query, version, dirty); err != nil { - if errRollback := tx.Rollback(); errRollback != nil { - err = multierror.Append(err, errRollback) - } - return &database.Error{OrigErr: err, Query: []byte(query)} - } - } - - if err = tx.Commit(); err != nil { - return &database.Error{OrigErr: err, Err: "transaction commit failed"} - } - - return nil -} - -func (m *Sqlite) Version() (version int, dirty bool, err error) { - query := "SELECT version, dirty FROM " + m.config.MigrationsTable + " LIMIT 1" - err = m.db.QueryRow(query).Scan(&version, &dirty) - if err != nil { - return database.NilVersion, false, nil - } - return version, dirty, nil -} diff --git a/database/migration/default_creator.go b/database/migration/creator.go similarity index 71% rename from database/migration/default_creator.go rename to database/migration/creator.go index b00935f06..55ddce65e 100644 --- a/database/migration/default_creator.go +++ b/database/migration/creator.go @@ -10,15 +10,15 @@ import ( "github.com/goravel/framework/support/str" ) -type DefaultCreator struct { +type Creator struct { } -func NewDefaultCreator() *DefaultCreator { - return &DefaultCreator{} +func NewCreator() *Creator { + return &Creator{} } // GetStub Get the migration stub file. -func (r *DefaultCreator) GetStub(table string, create bool) string { +func (r *Creator) GetStub(table string, create bool) string { if table == "" { return Stubs{}.Empty() } @@ -31,7 +31,7 @@ func (r *DefaultCreator) GetStub(table string, create bool) string { } // PopulateStub Populate the place-holders in the migration stub. -func (r *DefaultCreator) PopulateStub(stub, signature, table string) string { +func (r *Creator) PopulateStub(stub, signature, table string) string { stub = strings.ReplaceAll(stub, "DummyMigration", str.Of(signature).Prepend("m_").Studly().String()) stub = strings.ReplaceAll(stub, "DummySignature", signature) stub = strings.ReplaceAll(stub, "DummyTable", table) @@ -40,13 +40,13 @@ func (r *DefaultCreator) PopulateStub(stub, signature, table string) string { } // GetPath Get the full path to the migration. -func (r *DefaultCreator) GetPath(name string) string { +func (r *Creator) GetPath(name string) string { pwd, _ := os.Getwd() return filepath.Join(pwd, "database", "migrations", name+".go") } // GetFileName Get the full path to the migration. -func (r *DefaultCreator) GetFileName(name string) string { +func (r *Creator) GetFileName(name string) string { return fmt.Sprintf("%s_%s", carbon.Now().ToShortDateTimeString(), name) } diff --git a/database/migration/default_creator_test.go b/database/migration/creator_test.go similarity index 97% rename from database/migration/default_creator_test.go rename to database/migration/creator_test.go index ea1e2708c..ce011a66f 100644 --- a/database/migration/default_creator_test.go +++ b/database/migration/creator_test.go @@ -10,7 +10,7 @@ import ( type DefaultCreatorSuite struct { suite.Suite - defaultCreator *DefaultCreator + defaultCreator *Creator } func TestDefaultCreatorSuite(t *testing.T) { @@ -18,7 +18,7 @@ func TestDefaultCreatorSuite(t *testing.T) { } func (s *DefaultCreatorSuite) SetupTest() { - s.defaultCreator = NewDefaultCreator() + s.defaultCreator = NewCreator() } func (s *DefaultCreatorSuite) TestPopulateStub() { diff --git a/database/migration/default_migrator.go b/database/migration/migrator.go similarity index 80% rename from database/migration/default_migrator.go rename to database/migration/migrator.go index 196fac678..8ed7dff65 100644 --- a/database/migration/default_migrator.go +++ b/database/migration/migrator.go @@ -13,23 +13,23 @@ import ( supportfile "github.com/goravel/framework/support/file" ) -type DefaultMigrator struct { +type Migrator struct { artisan console.Artisan - creator *DefaultCreator + creator *Creator repository contractsmigration.Repository schema contractsschema.Schema } -func NewDefaultMigrator(artisan console.Artisan, schema contractsschema.Schema, table string) *DefaultMigrator { - return &DefaultMigrator{ +func NewMigrator(artisan console.Artisan, schema contractsschema.Schema, table string) *Migrator { + return &Migrator{ artisan: artisan, - creator: NewDefaultCreator(), + creator: NewCreator(), repository: NewRepository(schema, table), schema: schema, } } -func (r *DefaultMigrator) Create(name string) error { +func (r *Migrator) Create(name string) error { table, create := TableGuesser{}.Guess(name) stub := r.creator.GetStub(table, create) @@ -45,8 +45,7 @@ func (r *DefaultMigrator) Create(name string) error { return nil } -// TODO Remove this function and move the logic to the migrate:fresh command when the sql migrator is removed. -func (r *DefaultMigrator) Fresh() error { +func (r *Migrator) Fresh() error { if err := r.artisan.Call("db:wipe --force"); err != nil { return err } @@ -57,7 +56,7 @@ func (r *DefaultMigrator) Fresh() error { return nil } -func (r *DefaultMigrator) Reset() error { +func (r *Migrator) Reset() error { ran, err := r.repository.GetRan() if err != nil { return err @@ -66,7 +65,7 @@ func (r *DefaultMigrator) Reset() error { return r.Rollback(len(ran), 0) } -func (r *DefaultMigrator) Rollback(step, batch int) error { +func (r *Migrator) Rollback(step, batch int) error { files, err := r.getFilesForRollback(step, batch) if err != nil { return err @@ -97,7 +96,7 @@ func (r *DefaultMigrator) Rollback(step, batch int) error { return nil } -func (r *DefaultMigrator) Run() error { +func (r *Migrator) Run() error { if err := r.prepareDatabase(); err != nil { return err } @@ -112,7 +111,7 @@ func (r *DefaultMigrator) Run() error { return r.runPending(pendingMigrations) } -func (r *DefaultMigrator) Status() ([]contractsmigration.Status, error) { +func (r *Migrator) Status() ([]contractsmigration.Status, error) { if !r.repository.RepositoryExists() { color.Warningln("Migration table not found") @@ -134,7 +133,7 @@ func (r *DefaultMigrator) Status() ([]contractsmigration.Status, error) { return migrationStatus, nil } -func (r *DefaultMigrator) getFilesForRollback(step, batch int) ([]contractsmigration.File, error) { +func (r *Migrator) getFilesForRollback(step, batch int) ([]contractsmigration.File, error) { if step > 0 { return r.repository.GetMigrationsByStep(step) } @@ -146,7 +145,7 @@ func (r *DefaultMigrator) getFilesForRollback(step, batch int) ([]contractsmigra return r.repository.GetLast() } -func (r *DefaultMigrator) getMigrationViaFile(file contractsmigration.File) contractsschema.Migration { +func (r *Migrator) getMigrationViaFile(file contractsmigration.File) contractsschema.Migration { for _, migration := range r.schema.Migrations() { if migration.Signature() == file.Migration { return migration @@ -156,7 +155,7 @@ func (r *DefaultMigrator) getMigrationViaFile(file contractsmigration.File) cont return nil } -func (r *DefaultMigrator) getStatusForMigrations(batches []contractsmigration.File) []contractsmigration.Status { +func (r *Migrator) getStatusForMigrations(batches []contractsmigration.File) []contractsmigration.Status { var migrationStatus []contractsmigration.Status for _, migration := range r.schema.Migrations() { @@ -185,7 +184,7 @@ func (r *DefaultMigrator) getStatusForMigrations(batches []contractsmigration.Fi return migrationStatus } -func (r *DefaultMigrator) pendingMigrations(ran []string) []contractsschema.Migration { +func (r *Migrator) pendingMigrations(ran []string) []contractsschema.Migration { var pendingMigrations []contractsschema.Migration for _, migration := range r.schema.Migrations() { if !slices.Contains(ran, migration.Signature()) { @@ -196,7 +195,7 @@ func (r *DefaultMigrator) pendingMigrations(ran []string) []contractsschema.Migr return pendingMigrations } -func (r *DefaultMigrator) prepareDatabase() error { +func (r *Migrator) prepareDatabase() error { if r.repository.RepositoryExists() { return nil } @@ -204,7 +203,7 @@ func (r *DefaultMigrator) prepareDatabase() error { return r.repository.CreateRepository() } -func (r *DefaultMigrator) printTitle(maxNameLength int) { +func (r *Migrator) printTitle(maxNameLength int) { color.Default().Print(fmt.Sprintf("%-*s", maxNameLength, "Migration name")) color.Default().Println(" | Batch / Status") for i := 0; i < maxNameLength+17; i++ { @@ -213,7 +212,7 @@ func (r *DefaultMigrator) printTitle(maxNameLength int) { color.Default().Println() } -func (r *DefaultMigrator) runPending(migrations []contractsschema.Migration) error { +func (r *Migrator) runPending(migrations []contractsschema.Migration) error { if len(migrations) == 0 { color.Infoln("Nothing to migrate") @@ -238,7 +237,7 @@ func (r *DefaultMigrator) runPending(migrations []contractsschema.Migration) err return nil } -func (r *DefaultMigrator) runDown(migration contractsschema.Migration) error { +func (r *Migrator) runDown(migration contractsschema.Migration) error { defaultConnection := r.schema.GetConnection() defaultQuery := r.schema.Orm().Query() if connectionMigration, ok := migration.(contractsschema.Connection); ok { @@ -267,7 +266,7 @@ func (r *DefaultMigrator) runDown(migration contractsschema.Migration) error { return r.repository.Delete(migration.Signature()) } -func (r *DefaultMigrator) runUp(migration contractsschema.Migration, batch int) error { +func (r *Migrator) runUp(migration contractsschema.Migration, batch int) error { defaultConnection := r.schema.GetConnection() defaultQuery := r.schema.Orm().Query() if connectionMigration, ok := migration.(contractsschema.Connection); ok { diff --git a/database/migration/default_migrator_test.go b/database/migration/migrator_test.go similarity index 98% rename from database/migration/default_migrator_test.go rename to database/migration/migrator_test.go index 3036d92f6..bdd18e75b 100644 --- a/database/migration/default_migrator_test.go +++ b/database/migration/migrator_test.go @@ -84,7 +84,7 @@ func (s *DefaultMigratorWithDBSuite) TestRun() { testMigration, }) - migrator := NewDefaultMigrator(nil, schema, "migrations") + migrator := NewMigrator(nil, schema, "migrations") s.NoError(migrator.Run()) s.True(schema.HasTable("users")) @@ -104,7 +104,7 @@ func (s *DefaultMigratorWithDBSuite) TestReset() { testMigration, }) - migrator := NewDefaultMigrator(nil, schema, "migrations") + migrator := NewMigrator(nil, schema, "migrations") s.NoError(migrator.Run()) s.True(schema.HasTable("users")) @@ -123,7 +123,7 @@ func (s *DefaultMigratorWithDBSuite) TestRollback() { testMigration, }) - migrator := NewDefaultMigrator(nil, schema, "migrations") + migrator := NewMigrator(nil, schema, "migrations") s.NoError(migrator.Run()) s.True(schema.HasTable("users")) @@ -138,7 +138,7 @@ func (s *DefaultMigratorWithDBSuite) TestStatus() { s.Run(driver.String(), func() { schema := databaseschema.GetTestSchema(testQuery, s.driverToTestQuery) testMigration := NewTestMigration(schema) - migrator := NewDefaultMigrator(nil, schema, "migrations") + migrator := NewMigrator(nil, schema, "migrations") status, err := migrator.Status() s.NoError(err) s.Len(status, 0) @@ -178,7 +178,7 @@ func TestDefaultMigratorWithPostgresSchema(t *testing.T) { schema.Register([]contractsschema.Migration{ testMigration, }) - migrator := NewDefaultMigrator(nil, schema, "migrations") + migrator := NewMigrator(nil, schema, "migrations") assert.NoError(t, migrator.Run()) assert.True(t, schema.HasTable("users")) @@ -202,7 +202,7 @@ func TestDefaultMigratorWithSqlserverSchema(t *testing.T) { schema.Register([]contractsschema.Migration{ testMigration, }) - migrator := NewDefaultMigrator(nil, schema, "migrations") + migrator := NewMigrator(nil, schema, "migrations") assert.NoError(t, migrator.Run()) assert.True(t, schema.HasTable("goravel.users")) @@ -215,7 +215,7 @@ type DefaultMigratorSuite struct { mockArtisan *mocksconsole.Artisan mockRepository *mocksmigration.Repository mockSchema *mocksschema.Schema - migrator *DefaultMigrator + migrator *Migrator } func TestDefaultMigratorSuite(t *testing.T) { @@ -227,9 +227,9 @@ func (s *DefaultMigratorSuite) SetupTest() { s.mockRepository = mocksmigration.NewRepository(s.T()) s.mockSchema = mocksschema.NewSchema(s.T()) - s.migrator = &DefaultMigrator{ + s.migrator = &Migrator{ artisan: s.mockArtisan, - creator: NewDefaultCreator(), + creator: NewCreator(), repository: s.mockRepository, schema: s.mockSchema, } diff --git a/database/migration/sql_creator.go b/database/migration/sql_creator.go deleted file mode 100644 index 2934c584a..000000000 --- a/database/migration/sql_creator.go +++ /dev/null @@ -1,75 +0,0 @@ -package migration - -import ( - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/goravel/framework/contracts/database" - "github.com/goravel/framework/support/carbon" -) - -type SqlCreator struct { - driver database.Driver - charset string -} - -func NewSqlCreator(driver database.Driver, charset string) *SqlCreator { - return &SqlCreator{ - driver: driver, - charset: charset, - } -} - -// GetPath Get the full path to the migration. -func (r *SqlCreator) GetPath(name string, category string) string { - pwd, _ := os.Getwd() - - return filepath.Join(pwd, "database", "migrations", fmt.Sprintf("%s_%s.%s.sql", carbon.Now().ToShortDateTimeString(), name, category)) -} - -// GetStub Get the migration stub file. -func (r *SqlCreator) GetStub(table string, create bool) (string, string) { - if table == "" { - return "", "" - } - - switch r.driver { - case database.DriverPostgres: - if create { - return PostgresStubs{}.CreateUp(), PostgresStubs{}.CreateDown() - } - - return PostgresStubs{}.UpdateUp(), PostgresStubs{}.UpdateDown() - case database.DriverSqlite: - if create { - return SqliteStubs{}.CreateUp(), SqliteStubs{}.CreateDown() - } - - return SqliteStubs{}.UpdateUp(), SqliteStubs{}.UpdateDown() - case database.DriverSqlserver: - if create { - return SqlserverStubs{}.CreateUp(), SqlserverStubs{}.CreateDown() - } - - return SqlserverStubs{}.UpdateUp(), SqlserverStubs{}.UpdateDown() - default: - if create { - return MysqlStubs{}.CreateUp(), MysqlStubs{}.CreateDown() - } - - return MysqlStubs{}.UpdateUp(), MysqlStubs{}.UpdateDown() - } -} - -// PopulateStub Populate the place-holders in the migration stub. -func (r *SqlCreator) PopulateStub(stub string, table string) string { - stub = strings.ReplaceAll(stub, "DummyDatabaseCharset", r.charset) - - if table != "" { - stub = strings.ReplaceAll(stub, "DummyTable", table) - } - - return stub -} diff --git a/database/migration/sql_creator_test.go b/database/migration/sql_creator_test.go deleted file mode 100644 index d81095e89..000000000 --- a/database/migration/sql_creator_test.go +++ /dev/null @@ -1,150 +0,0 @@ -package migration - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/goravel/framework/contracts/database" - "github.com/goravel/framework/support/carbon" - "github.com/goravel/framework/support/str" -) - -type SqlCreatorSuite struct { - suite.Suite - sqlCreator *SqlCreator -} - -func TestSqlCreatorSuite(t *testing.T) { - suite.Run(t, &SqlCreatorSuite{}) -} - -func (s *SqlCreatorSuite) SetupTest() { - s.sqlCreator = NewSqlCreator("postgres", "utf8mb4") -} - -func (s *SqlCreatorSuite) TestGetPath() { - now := carbon.FromDateTime(2024, 8, 17, 21, 45, 1) - carbon.SetTestNow(now) - - pwd, _ := os.Getwd() - path := filepath.Join(pwd, "database", "migrations") - - s.Equal(filepath.Join(path, "20240817214501_create_users_table.up.sql"), s.sqlCreator.GetPath("create_users_table", "up")) - s.Equal(filepath.Join(path, "20240817214501_create_users_table.down.sql"), s.sqlCreator.GetPath("create_users_table", "down")) - - carbon.UnsetTestNow() -} - -func (s *SqlCreatorSuite) TestPopulateStub() { - tests := []struct { - name string - driver database.Driver - table string - create bool - expectUp string - expectDown string - }{ - { - name: "table is empty", - }, - { - name: "mysql - create template", - driver: "mysql", - table: "users", - create: true, - expectUp: `CREATE TABLE users ( - id bigint(20) unsigned NOT NULL AUTO_INCREMENT, - created_at datetime(3) NOT NULL, - updated_at datetime(3) NOT NULL, - PRIMARY KEY (id), - KEY idx_users_created_at (created_at), - KEY idx_users_updated_at (updated_at) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;`, - expectDown: `DROP TABLE IF EXISTS users;`, - }, - { - name: "mysql - update template", - driver: "mysql", - table: "users", - create: false, - expectUp: `ALTER TABLE users ADD column varchar(255) COMMENT '';`, - expectDown: `ALTER TABLE users DROP COLUMN column;`, - }, - { - name: "postgres - create template", - driver: "postgres", - table: "users", - create: true, - expectUp: `CREATE TABLE users ( - id SERIAL PRIMARY KEY NOT NULL, - created_at timestamp NOT NULL, - updated_at timestamp NOT NULL -);`, - expectDown: `DROP TABLE IF EXISTS users;`, - }, - { - name: "postgres - update template", - driver: "postgres", - table: "users", - create: false, - expectUp: `ALTER TABLE users ADD column varchar(255) NOT NULL;`, - expectDown: `ALTER TABLE users DROP COLUMN column;`, - }, - { - name: "sqlite - create template", - driver: "sqlite", - table: "users", - create: true, - expectUp: `CREATE TABLE users ( - id integer PRIMARY KEY AUTOINCREMENT NOT NULL, - created_at datetime NOT NULL, - updated_at datetime NOT NULL -);`, - expectDown: `DROP TABLE IF EXISTS users;`, - }, - { - name: "sqlite - update template", - driver: "sqlite", - table: "users", - create: false, - expectUp: `ALTER TABLE users ADD column text;`, - expectDown: `ALTER TABLE users DROP COLUMN column;`, - }, - { - name: "sqlserver - create template", - driver: "sqlserver", - table: "users", - create: true, - expectUp: `CREATE TABLE users ( - id bigint NOT NULL IDENTITY(1,1), - created_at datetime NOT NULL, - updated_at datetime NOT NULL, - PRIMARY KEY (id) -);`, - expectDown: `DROP TABLE IF EXISTS users;`, - }, - { - name: "sqlserver - update template", - driver: "sqlserver", - table: "users", - create: false, - expectUp: `ALTER TABLE users ADD column varchar(255);`, - expectDown: `ALTER TABLE users DROP COLUMN column;`, - }, - } - - for _, test := range tests { - s.Run(test.name, func() { - sqlCreator := NewSqlCreator(test.driver, "utf8mb4") - upStub, downStub := sqlCreator.GetStub(test.table, test.create) - up := sqlCreator.PopulateStub(upStub, test.table) - down := sqlCreator.PopulateStub(downStub, test.table) - - s.Equal(test.expectUp, str.Of(up).RTrim("\n").String()) - s.Equal(test.expectDown, str.Of(down).RTrim("\n").String()) - }) - } -} diff --git a/database/migration/sql_migrator.go b/database/migration/sql_migrator.go deleted file mode 100644 index 6a8ceaabc..000000000 --- a/database/migration/sql_migrator.go +++ /dev/null @@ -1,211 +0,0 @@ -package migration - -import ( - "database/sql" - "fmt" - - "github.com/golang-migrate/migrate/v4" - migratedatabase "github.com/golang-migrate/migrate/v4/database" - "github.com/golang-migrate/migrate/v4/database/mysql" - "github.com/golang-migrate/migrate/v4/database/postgres" - "github.com/golang-migrate/migrate/v4/database/sqlserver" - _ "github.com/golang-migrate/migrate/v4/source/file" - - "github.com/goravel/framework/contracts/config" - "github.com/goravel/framework/contracts/database" - "github.com/goravel/framework/contracts/database/migration" - "github.com/goravel/framework/database/console/driver" - databasedb "github.com/goravel/framework/database/db" - "github.com/goravel/framework/errors" - "github.com/goravel/framework/support" - "github.com/goravel/framework/support/color" - "github.com/goravel/framework/support/file" -) - -// TODO Remove in v1.16 -type SqlMigrator struct { - configBuilder *databasedb.ConfigBuilder - creator *SqlCreator - migrator *migrate.Migrate - table string -} - -func NewSqlMigrator(config config.Config) (*SqlMigrator, error) { - connection := config.GetString("database.default") - charset := config.GetString(fmt.Sprintf("database.connections.%s.charset", connection)) - dbDriver := database.Driver(config.GetString(fmt.Sprintf("database.connections.%s.driver", connection))) - table := config.GetString("database.migrations.table") - configBuilder := databasedb.NewConfigBuilder(config, connection) - migrator, err := getMigrator(configBuilder, table) - if err != nil { - return nil, err - } - - return &SqlMigrator{ - configBuilder: configBuilder, - creator: NewSqlCreator(dbDriver, charset), - migrator: migrator, - table: table, - }, nil -} - -func (r *SqlMigrator) Create(name string) error { - table, create := TableGuesser{}.Guess(name) - - upStub, downStub := r.creator.GetStub(table, create) - - // Create the up.sql file. - if err := file.Create(r.creator.GetPath(name, "up"), r.creator.PopulateStub(upStub, table)); err != nil { - return err - } - - // Create the down.sql file. - if err := file.Create(r.creator.GetPath(name, "down"), r.creator.PopulateStub(downStub, table)); err != nil { - return err - } - - return nil -} - -func (r *SqlMigrator) Fresh() error { - if err := r.migrator.Drop(); err != nil && !errors.Is(err, migrate.ErrNoChange) { - return err - } - - // Recreate the migrations table. - migrator, err := getMigrator(r.configBuilder, r.table) - if err != nil { - return err - } - - r.migrator = migrator - - return r.Run() -} - -func (r *SqlMigrator) Reset() error { - if err := r.migrator.Down(); err != nil && !errors.Is(err, migrate.ErrNoChange) { - return errors.MigrationResetFailed.Args(err) - } - - color.Successln("Migration reset success") - - return nil -} - -func (r *SqlMigrator) Rollback(step, batch int) error { - if err := r.migrator.Steps(-step); err != nil { - var errShortLimit migrate.ErrShortLimit - if errors.Is(err, migrate.ErrNoChange) || errors.Is(err, migrate.ErrNilVersion) || errors.As(err, &errShortLimit) { - return nil - } - - return errors.MigrationRollbackFailed.Args(err) - } - - return nil -} - -func (r *SqlMigrator) Run() error { - if err := r.migrator.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) { - return err - } - - return nil -} - -func (r *SqlMigrator) Status() ([]migration.Status, error) { - version, dirty, err := r.migrator.Version() - if err != nil { - if errors.Is(err, migrate.ErrNilVersion) { - color.Warningln("No migrations found") - - return nil, nil - } else { - return nil, errors.MigrationGetStatusFailed.Args(err) - } - } - if dirty { - color.Warningln("Migration status: dirty") - } - - color.Successln(fmt.Sprintf("Migration version: %d", version)) - - return nil, nil -} - -func getMigrator(configBuilder *databasedb.ConfigBuilder, table string) (*migrate.Migrate, error) { - path := "file://./database/migrations" - if support.RelativePath != "" { - path = fmt.Sprintf("file://%s/database/migrations", support.RelativePath) - } - - writeConfigs := configBuilder.Writes() - if len(writeConfigs) == 0 { - return nil, errors.OrmDatabaseConfigNotFound - } - - writeConfig := writeConfigs[0] - dsn := databasedb.Dsn(writeConfigs[0]) - if dsn == "" { - return nil, errors.OrmFailedToGenerateDNS - } - - var ( - databaseName string - db *sql.DB - dbDriver migratedatabase.Driver - err error - ) - - switch writeConfig.Driver { - case database.DriverMysql: - databaseName = "mysql" - db, err = sql.Open(databaseName, dsn) - if err != nil { - return nil, err - } - - dbDriver, err = mysql.WithInstance(db, &mysql.Config{ - MigrationsTable: table, - }) - case database.DriverPostgres: - databaseName = "postgres" - db, err = sql.Open(databaseName, dsn) - if err != nil { - return nil, err - } - - dbDriver, err = postgres.WithInstance(db, &postgres.Config{ - MigrationsTable: table, - }) - case database.DriverSqlite: - databaseName = "sqlite3" - db, err = sql.Open("sqlite", dsn) - if err != nil { - return nil, err - } - - dbDriver, err = driver.WithInstance(db, &driver.Config{ - MigrationsTable: table, - }) - case database.DriverSqlserver: - databaseName = "sqlserver" - db, err = sql.Open(databaseName, dsn) - if err != nil { - return nil, err - } - - dbDriver, err = sqlserver.WithInstance(db, &sqlserver.Config{ - MigrationsTable: table, - }) - default: - err = errors.OrmDriverNotSupported.Args(writeConfig.Connection) - } - - if err != nil { - return nil, err - } - - return migrate.NewWithDatabaseInstance(path, databaseName, dbDriver) -} diff --git a/database/migration/sql_migrator_test.go b/database/migration/sql_migrator_test.go deleted file mode 100644 index 0a4d859c5..000000000 --- a/database/migration/sql_migrator_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package migration - -import ( - "io" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - contractsdatabase "github.com/goravel/framework/contracts/database" - "github.com/goravel/framework/contracts/database/orm" - databasedb "github.com/goravel/framework/database/db" - "github.com/goravel/framework/database/gorm" - "github.com/goravel/framework/support/carbon" - "github.com/goravel/framework/support/color" - "github.com/goravel/framework/support/env" - "github.com/goravel/framework/support/file" -) - -type SqlMigratorSuite struct { - suite.Suite - driverToTestQuery map[contractsdatabase.Driver]*gorm.TestQuery -} - -func TestSqlMigratorSuite(t *testing.T) { - if env.IsWindows() { - t.Skip("Skip test that using Docker") - } - - suite.Run(t, &SqlMigratorSuite{}) -} - -func (s *SqlMigratorSuite) SetupTest() { - s.driverToTestQuery = gorm.NewTestQueries().Queries() -} - -func (s *SqlMigratorSuite) TearDownTest() { - s.NoError(file.Remove("database")) - if s.driverToTestQuery[contractsdatabase.DriverSqlite] != nil { - s.NoError(s.driverToTestQuery[contractsdatabase.DriverSqlite].Docker().Shutdown()) - } -} - -func (s *SqlMigratorSuite) TestCreate() { - now := carbon.FromDateTime(2024, 8, 17, 21, 45, 1) - carbon.SetTestNow(now) - defer carbon.UnsetTestNow() - - pwd, err := os.Getwd() - s.NoError(err) - - path := filepath.Join(pwd, "database", "migrations") - name := "create_users_table" - - for driver, testQuery := range s.driverToTestQuery { - migrator, _ := getTestSqlMigrator(s.T(), driver, testQuery) - - s.NoError(migrator.Create(name)) - - upFile := filepath.Join(path, "20240817214501_"+name+".up.sql") - downFile := filepath.Join(path, "20240817214501_"+name+".down.sql") - - s.True(file.Exists(upFile)) - s.True(file.Exists(downFile)) - } -} - -func (s *SqlMigratorSuite) TestFresh() { - for driver, testQuery := range s.driverToTestQuery { - s.Run(driver.String(), func() { - migrator, query := getTestSqlMigrator(s.T(), driver, testQuery) - - err := migrator.Run() - s.NoError(err) - - err = migrator.Fresh() - s.NoError(err) - - var agent Agent - err = query.Where("name", "goravel").First(&agent) - s.NoError(err) - s.True(agent.ID > 0) - }) - } -} - -func (s *SqlMigratorSuite) TestRollback() { - for driver, testQuery := range s.driverToTestQuery { - s.Run(driver.String(), func() { - migrator, query := getTestSqlMigrator(s.T(), driver, testQuery) - - err := migrator.Run() - s.NoError(err) - - var agent Agent - err = query.Where("name", "goravel").First(&agent) - s.NoError(err) - s.True(agent.ID > 0) - - err = migrator.Rollback(1, 0) - s.NoError(err) - - var agent1 Agent - err = query.Where("name", "goravel").First(&agent1) - s.NotNil(err) - }) - } -} - -func (s *SqlMigratorSuite) TestRun() { - for driver, testQuery := range s.driverToTestQuery { - s.Run(driver.String(), func() { - migrator, query := getTestSqlMigrator(s.T(), driver, testQuery) - - err := migrator.Run() - s.NoError(err) - - var agent Agent - s.NoError(query.Where("name", "goravel").First(&agent)) - s.True(agent.ID > 0) - - err = migrator.Run() - s.NoError(err) - }) - } -} - -func (s *SqlMigratorSuite) TestStatus() { - for driver, testQuery := range s.driverToTestQuery { - s.Run(driver.String(), func() { - migrator, _ := getTestSqlMigrator(s.T(), driver, testQuery) - - s.Equal("\x1b[30;43m\x1b[30;43m WARNING \x1b[0m\x1b[0m \x1b[33m\x1b[33mNo migrations found\x1b[0m\x1b[0m\n", color.CaptureOutput(func(w io.Writer) { - status, err := migrator.Status() - s.NoError(err) - s.Nil(status) - })) - - err := migrator.Run() - s.NoError(err) - - s.Equal("\x1b[30;42m\x1b[30;42m SUCCESS \x1b[0m\x1b[0m \x1b[32m\x1b[32mMigration version: 20230311160527\x1b[0m\x1b[0m\n", color.CaptureOutput(func(w io.Writer) { - status, err := migrator.Status() - s.NoError(err) - s.Nil(status) - })) - }) - } -} - -func getTestSqlMigrator(t *testing.T, driver contractsdatabase.Driver, testQuery *gorm.TestQuery) (*SqlMigrator, orm.Query) { - query := testQuery.Query() - mockConfig := testQuery.MockConfig() - CreateTestMigrations(driver) - - table := "migrations" - configBuilder := databasedb.NewConfigBuilder(mockConfig, driver.String()) - migrator, err := getMigrator(configBuilder, table) - require.NoError(t, err) - - return &SqlMigrator{ - configBuilder: databasedb.NewConfigBuilder(mockConfig, driver.String()), - creator: NewSqlCreator(driver, "utf8mb4"), - migrator: migrator, - table: table, - }, query -} diff --git a/database/service_provider.go b/database/service_provider.go index 99b43d148..af12df4af 100644 --- a/database/service_provider.go +++ b/database/service_provider.go @@ -4,7 +4,6 @@ import ( "context" contractsconsole "github.com/goravel/framework/contracts/console" - contractsmigration "github.com/goravel/framework/contracts/database/migration" "github.com/goravel/framework/contracts/foundation" "github.com/goravel/framework/database/console" consolemigration "github.com/goravel/framework/database/console/migration" @@ -82,23 +81,7 @@ func (r *ServiceProvider) registerCommands(app foundation.Application) { seeder := app.MakeSeeder() if artisan != nil && config != nil && log != nil && schema != nil && seeder != nil { - var migrator contractsmigration.Migrator - - driver := config.GetString("database.migrations.driver") - if driver == contractsmigration.MigratorDefault { - migrator = migration.NewDefaultMigrator(artisan, schema, config.GetString("database.migrations.table")) - } else if driver == contractsmigration.MigratorSql { - var err error - migrator, err = migration.NewSqlMigrator(config) - if err != nil { - log.Error(errors.MigrationSqlMigratorInit.Args(err).SetModule(errors.ModuleMigration)) - return - } - } else { - log.Error(errors.MigrationUnsupportedDriver.Args(driver).SetModule(errors.ModuleMigration)) - return - } - + migrator := migration.NewMigrator(artisan, schema, config.GetString("database.migrations.table")) artisan.Register([]contractsconsole.Command{ consolemigration.NewMigrateMakeCommand(migrator), consolemigration.NewMigrateCommand(migrator), diff --git a/errors/list.go b/errors/list.go index 8ff6b5271..14ce72c2e 100644 --- a/errors/list.go +++ b/errors/list.go @@ -74,16 +74,14 @@ var ( LogDriverNotSupported = New("invalid driver: %s, only support stack, single, daily, custom").SetModule(ModuleLog) LogEmptyLogFilePath = New("empty log file path").SetModule(ModuleLog) - MigrationCreateFailed = New("Create migration failed: %v") - MigrationFreshFailed = New("migration fresh failed: %v") - MigrationGetStatusFailed = New("get migration status failed: %v") - MigrationMigrateFailed = New("migrate failed: %v") - MigrationNameIsRequired = New("migration name cannot be empty") - MigrationRefreshFailed = New("migration refresh failed: %v") - MigrationResetFailed = New("migration reset failed: %v") - MigrationRollbackFailed = New("migration rollback failed: %v") - MigrationSqlMigratorInit = New("failed to init sql migration driver: %s") - MigrationUnsupportedDriver = New("unsupported migration driver: %s") + MigrationCreateFailed = New("Create migration failed: %v") + MigrationFreshFailed = New("migration fresh failed: %v") + MigrationGetStatusFailed = New("get migration status failed: %v") + MigrationMigrateFailed = New("migrate failed: %v") + MigrationNameIsRequired = New("migration name cannot be empty") + MigrationRefreshFailed = New("migration refresh failed: %v") + MigrationResetFailed = New("migration reset failed: %v") + MigrationRollbackFailed = New("migration rollback failed: %v") OrmDatabaseConfigNotFound = New("not found database configuration") OrmDriverNotSupported = New("invalid driver: %s, only support mysql, postgres, sqlite and sqlserver") diff --git a/go.mod b/go.mod index eab94737f..bc7ff20aa 100644 --- a/go.mod +++ b/go.mod @@ -13,16 +13,13 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/dromara/carbon/v2 v2.5.2 github.com/gabriel-vasile/mimetype v1.4.8 - github.com/glebarez/go-sqlite v1.22.0 github.com/glebarez/sqlite v1.11.0 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/golang-jwt/jwt/v5 v5.2.1 - github.com/golang-migrate/migrate/v4 v4.18.1 github.com/golang/protobuf v1.5.4 github.com/google/uuid v1.6.0 github.com/gookit/validate v1.5.4 github.com/goravel/file-rotatelogs/v2 v2.4.2 - github.com/hashicorp/go-multierror v1.1.1 github.com/pterm/pterm v0.12.80 github.com/redis/go-redis/v9 v9.7.0 github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 @@ -34,7 +31,6 @@ require ( github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.10.0 github.com/urfave/cli/v2 v2.27.5 - go.uber.org/atomic v1.11.0 golang.org/x/crypto v0.32.0 golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 google.golang.org/grpc v1.69.2 @@ -54,11 +50,6 @@ require ( cloud.google.com/go/iam v1.1.6 // indirect cloud.google.com/go/pubsub v1.36.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.16 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae // indirect github.com/atotto/clipboard v0.1.4 // indirect github.com/aws/aws-sdk-go v1.49.6 // indirect @@ -77,13 +68,13 @@ require ( github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/glebarez/go-sqlite v1.22.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-redsync/redsync/v4 v4.8.1 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/go-stack/stack v1.8.0 // indirect - github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -96,6 +87,7 @@ require ( github.com/gookit/filter v1.2.2 // indirect github.com/gookit/goutil v0.6.18 github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect @@ -107,7 +99,6 @@ require ( github.com/kelseyhightower/envconfig v1.4.0 // indirect github.com/klauspost/compress v1.17.2 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect - github.com/lib/pq v1.10.9 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -127,6 +118,7 @@ require ( github.com/rabbitmq/amqp091-go v1.9.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -148,6 +140,7 @@ require ( go.opentelemetry.io/otel v1.31.0 // indirect go.opentelemetry.io/otel/metric v1.31.0 // indirect go.opentelemetry.io/otel/trace v1.31.0 // indirect + go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect diff --git a/go.sum b/go.sum index 875bfde73..0cb0a5313 100644 --- a/go.sum +++ b/go.sum @@ -69,20 +69,6 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 h1:MyVTgWR github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1/go.mod h1:GpPjLhVR9dnUoJMyHWSPy71xY9/lcmpzIPZXmF0FCVY= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest/adal v0.9.16 h1:P8An8Z9rH1ldbOLdFpxYorgOt2sywL9V24dAwWHPuGc= -github.com/Azure/go-autorest/autorest/adal v0.9.16/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= @@ -99,8 +85,6 @@ github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/ github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4= github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae h1:DcFpTQBYQ9Ct2d6sC7ol0/ynxc2pO1cpGUM+f4t5adg= github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae/go.mod h1:rJJ84PyA/Wlmw1hO+xTzV2wsSUon6J5ktg0g8BF2PuU= github.com/RichardKnop/machinery/v2 v2.0.13 h1:uo9htg+qNBi7UeUK3jcTBl3vTO/vvLKGaOdCOKePl50= @@ -167,18 +151,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dhui/dktest v0.4.3 h1:wquqUxAFdcUgabAVLvSCOKOlag5cIZuaOjYIBOWdsR0= -github.com/dhui/dktest v0.4.3/go.mod h1:zNK8IwktWzQRm6I/l2Wjp7MakiyaFWv4G1hjmodmMTs= -github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= -github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dromara/carbon/v2 v2.5.2 h1:GquNyA9Imda+LwS9FIzHhKg+foU2QPstH+S3idBRjKg= github.com/dromara/carbon/v2 v2.5.2/go.mod h1:zyPlND2o27sKKkRmdgLbk/qYxkmmH6Z4eE8OoM0w3DM= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= @@ -255,17 +229,10 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= -github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang-migrate/migrate/v4 v4.18.1 h1:JML/k+t4tpHCpQTCAD62Nu43NUFzHY4CV3uAuvHGC+Y= -github.com/golang-migrate/migrate/v4 v4.18.1/go.mod h1:HAX6m3sQgcdO81tdjn5exv20+3Kb13cmGli1hrD6hks= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= @@ -435,8 +402,6 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= @@ -458,15 +423,9 @@ github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4 github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -483,10 +442,6 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= -github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= @@ -655,7 +610,6 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=