Describe the feature
The migration should happen in two steps
- create all the tables without associations
- after table creation is done add the constraints defined in the model structs
Motivation
I have complex struct with lot of one to many & many to many relationships between tables
like this
type Organization struct {
ID uuid.UUID `json:"id" gorm:"primary_key; unique; type:uuid; column:id; default:uuid_generate_v4();"`
OrganizationID uuid.UUID `json:"organization_id" gorm:"type:uuid;default:uuid_generate_v4();"`
Locations []Location `json:"locations"`
Name string `json:"name"`
TimeZone string `json:"time_zone"`
Language string `json:"language"`
IsLatest bool `json:"is_latest" gorm:"default:true;index;"`
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
Users []User `json:"users"`
}
type User struct {
ID uuid.UUID `json:"id" gorm:"primary_key; unique; type:uuid; column:id; default:uuid_generate_v4();"`
OrganizationID uuid.UUID `json:"organization_id"`
Organization Organization `json:"organization" gorm:"foreignKey:OrganizationID;references:OrganizationID;"`
UserID uuid.UUID `json:"user_id" gorm:"type:uuid;default:uuid_generate_v4();"`
Name string `json:"name"`
Role userRole `json:"role" sql:"type:user_role"`
IsLatest bool `json:"is_latest" gorm:"default:true;index;"`
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
}
func main() {
conn := utils.ConstructDBConnString(utils.PostgresConfig{
SslMode: option.Some("disable"),
})
opts := gorm.Config{
DisableForeignKeyConstraintWhenMigrating: true,
}
db, err := gorm.Open(postgres.Open(conn), &opts)
if err != nil {
panic(err)
}
db.Exec(`CREATE EXTENSION IF NOT EXISTS "uuid-ossp";`)
err = db.AutoMigrate(
&domain.Organization{},
&domain.User{},
// &domain.Location{},
// &domain.Service{},
// &domain.Booking{},
)
if err != nil {
panic(err)
}
}
Currently i have to disable constraints creation because when it tries to create the organization table it also tries to create the constraint to user table but user table does not exist yet.
ERROR: relation "organizations" does not exist (SQLSTATE 42P01)
[0.190ms] [rows:0] ALTER TABLE "users" ADD CONSTRAINT "fk_organizations_users" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id")
panic: ERROR: relation "organizations" does not exist (SQLSTATE 42P01)
goroutine 1 [running]:
main.main()
Related Issues
After a lot of searching i couldn't find any issues related to this
Comment From: mdrokz
Apparently i was doing it wrong you have to specify foreign key like this in the users field instead of in the user struct
type Organization struct {
ID uuid.UUID `json:"id" gorm:"primary_key; unique; type:uuid; column:id; default:uuid_generate_v4();"`
OrganizationID uuid.UUID `json:"organization_id" gorm:"type:uuid;default:uuid_generate_v4();"`
Locations []Location `json:"locations"`
Name string `json:"name"`
TimeZone string `json:"time_zone"`
Language string `json:"language"`
IsLatest bool `json:"is_latest" gorm:"default:true;index;"`
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
Users []User `json:"users" gorm:"foreignKey:OrganizationID;references:OrganizationID;"`
}
and in order to load organization field in the user you can do it like this
db.Model(&domain.User{}).Preload("Organization", "organization_id = ?", o.OrganizationID).Find(&u)
Leaving this here in case anybody stumbles onto the same problem as the docs were confusing