Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report if AutoMigrate() will change the schema. #5635

Open
googollee opened this issue Aug 23, 2022 · 4 comments
Open

Report if AutoMigrate() will change the schema. #5635

googollee opened this issue Aug 23, 2022 · 4 comments
Assignees
Labels
type:feature_request feature request

Comments

@googollee
Copy link
Contributor

Describe the feature

Report if AutoMigrate() will change the schema.

One possible way:

  • With Session.DryRun = true, AutoMigrate() succeeds if no need to change schema, and panics if there is any changes of schema.

Motivation

I know AutoMigrate() won't break any data. But when a table has many records, ALTER COLUMN may take a long time to finish, which is not safe for prod.

I hope to know if there is any change of schema before applying the changes. I can notify people when the change appears and arrange a proper time to apply those changes.

I tried AutoMigrate() with Session.DryRun = true. No matter there is changes or not, AutoMigrate() panics with dry run mode unsupported.

Related Issues

I can't find any related issues.

@github-actions github-actions bot added the type:feature_request feature request label Aug 23, 2022
googollee added a commit to googollee/gorm that referenced this issue Aug 24, 2022
googollee added a commit to googollee/gorm that referenced this issue Aug 24, 2022
googollee added a commit to googollee/gorm that referenced this issue Aug 25, 2022
@googollee googollee mentioned this issue Aug 25, 2022
3 tasks
googollee added a commit to googollee/gorm that referenced this issue Aug 25, 2022
googollee added a commit to googollee/gorm that referenced this issue Aug 25, 2022
googollee added a commit to googollee/gorm that referenced this issue Aug 25, 2022
googollee added a commit to googollee/gorm that referenced this issue Sep 14, 2022
googollee added a commit to googollee/gorm that referenced this issue Sep 15, 2022
@jonerer
Copy link

jonerer commented Sep 26, 2022

I would also really like something like this. My usecase is that I would like gorm to generate a migration (in the form of SQL), that I can dump into a file to use with something like https://github.com/golang-migrate/migrate .

Actually running AutoMigrate() doesn't usually work if you have a whole team and multiple deployment environments; things always get out of sync, and it becomes a mess to sort everything out. So doing something like golang-migrate with specific steps saved in files, checked into the repo is usually the way to go in the end.

In my mind it should be something like
db.PrintMigrationDiff() or db.CalculateDbDiff() or so.

A function that returns a string wih the diff between the current state of the database and what the models say.

I don't really understand why you would want anything to "error" or "panic". Introspecting the database and comparing to the schema is a normal operation to perform, not an error state. What the user chooses to do with the information (quit the program or whatever) should be outside of what the db framework decides. Or?

@jonerer
Copy link

jonerer commented Sep 26, 2022

Hm looks like #5689 is something like that

@googollee
Copy link
Contributor Author

I don't really understand why you would want anything to "error" or "panic".

A diff would be better. An error/panic is the simple thing to know schema changing.

@molind
Copy link

molind commented Mar 3, 2023

I've ended up with this.

type SelectOnlyAllowedLogger struct {
	logger.Interface
}

func (sl SelectOnlyAllowedLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
	sql, _ := fc()
	if strings.HasPrefix(sql, "SELECT") {
		sl.Interface.Trace(ctx, begin, fc, err)
		return
	}
	log.Fatal("Migration required: ", sql)
}

func NewDB() *gorm.DB {
	db, err := gorm.Open(postgres.Open(common.Settings.DBConnectionString), &gorm.Config{PrepareStmt: true})
	if err != nil {
		log.Fatal("Failed to connect database", err)
	}

	migrateChecker := db.Session(&gorm.Session{Logger: SelectOnlyAllowedLogger{Interface: logger.Default}})
	model.AutoMigrate(migrateChecker)

	return db
}

Tried to provide custom migrator, and check if any of Add, Drop, Alter function is called. But since last update it calls AlterColumn for every column with unique index, then checks inside if there is an index already and skips any changes. This solution is really simple and it blocks any changes, since only SELECT functions are allowed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:feature_request feature request
Projects
None yet
Development

No branches or pull requests

4 participants