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

AutoMigrate should avoid migration if table structure not changed? #6398

Open
kkocdko opened this issue Jun 9, 2023 · 2 comments
Open

AutoMigrate should avoid migration if table structure not changed? #6398

kkocdko opened this issue Jun 9, 2023 · 2 comments
Assignees
Labels
type:feature_request feature request

Comments

@kkocdko
Copy link
Contributor

kkocdko commented Jun 9, 2023

Describe the feature

AutoMigrate is useful to migrate database but it runs migration every time even if the table structure (struct define) not changed.

Motivation

The AutoMigrate is prefixed with Auto, which should be more smart. And I found that some prime users like me just use AutoMigrate at the begining of program and image it will skip migration when possible (LOL).

Related Issues

If this feature was too complex to implement, maybe add this to docs?

@github-actions github-actions bot added the type:feature_request feature request label Jun 9, 2023
@jinzhu
Copy link
Member

jinzhu commented Jul 26, 2023

We are trying to achieve this goal, could you create a playground that could reproduce the case?

@kkocdko
Copy link
Contributor Author

kkocdko commented Jul 26, 2023

My personal method to run migrate on-demand. Just fit my personal usage.

package main

import (
	"encoding/json"
	"fmt"
	"reflect"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// MUST keep outputs stable
func GetDefine(v any) string {
	t := reflect.TypeOf(v)
	ret := "type " + t.Name() + " struct {\n"
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		ret += " " + field.Name + " " + field.Type.Name()
		tag := string(field.Tag)
		if tag != "" {
			ret += " `" + string(field.Tag) + "`"
		}
		ret += "\n"
	}
	ret += "}"
	return ret
}

func panicErr(v error, msg ...string) {
	if v != nil {
		if len(msg) != 0 {
			fmt.Println(msg[0])
		}
		panic(v)
	}
}

type KeyValue struct {
	Key   string
	Value []byte
}

type FooBar struct {
	Field1 string
	Field2 int
	Field3 byte
}

func initGorm() error {
	gormCfg := gorm.Config{}
	gormCfg.Logger.LogMode(logger.Info)
	dsn := "file:data.db"
	d, err := gorm.Open(sqlite.Open(dsn), &gormCfg)
	panicErr(err)

	// My personal method to run migrate on-demand
	defs := map[string]string{}
	kv := KeyValue{Key: "db_def"}
	if d.First(&kv).Error == nil {
		panicErr(json.Unmarshal(kv.Value, &defs))
	}
	for _, v := range []any{FooBar{}} {
		name, def := reflect.TypeOf(v).Name(), GetDefine(v)
		if defs[name] != def {
			panicErr(d.AutoMigrate(&v))
			defs[name] = def
			fmt.Printf("AutoMigrate: %v\n", name)
		}
	}
	kv.Value, _ = json.Marshal(defs)
	d.Save(&kv)

	return nil
}

func main() {
	initGorm()
}

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

2 participants