go-gorm / gorm

The fantastic ORM library for Golang, aims to be developer friendly
https://gorm.io
MIT License
37.05k stars 3.94k forks source link

`AutoMigrate` Does Not Update Existing Check Constraint #7211

Closed YidiDev closed 1 month ago

YidiDev commented 1 month ago

GORM Playground Link

Note: I attempted to create a GORM Playground Pull Request to reproduce this issue, but I encountered issues with the playground not functioning correctly. Therefore, I'm including a minimal reproducible example in this issue.

Description

Summary:

When modifying a check constraint on a model field and running AutoMigrate, GORM does not update the existing check constraint in the database if a constraint with the same name already exists. This issue is observed with SQLite and may affect other database dialects as well.


Steps to Reproduce:

  1. Set up the initial model with a check constraint and run AutoMigrate:

    package main
    
    import (
       "gorm.io/driver/sqlite"
       "gorm.io/gorm"
       "log"
    )
    
    type User struct {
       ID   uint
       Name string `gorm:"check:name_checker,name <> ''"`
    }
    
    func main() {
       db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
       if err != nil {
           log.Fatalf("failed to connect to database: %v", err)
       }
    
       if err = db.AutoMigrate(&User{}); err != nil {
           log.Fatalf("failed to migrate: %v", err)
       }
    }
  2. Modify the check constraint in the model and run AutoMigrate again:

    package main
    
    import (
       "gorm.io/driver/sqlite"
       "gorm.io/gorm"
       "log"
    )
    
    type User struct {
       ID   uint
       Name string `gorm:"check:name_checker,length(name) > 3"`
    }
    
    func main() {
       db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
       if err != nil {
           log.Fatalf("failed to connect to database: %v", err)
       }
    
       if err = db.AutoMigrate(&User{}); err != nil {
           log.Fatalf("failed to migrate after modification: %v", err)
       }
    }
  3. Attempt to insert data that violates the new constraint but satisfies the old one:

    package main
    
    import (
       "fmt"
       "gorm.io/driver/sqlite"
       "gorm.io/gorm"
       "log"
    )
    
    type User struct {
       ID   uint
       Name string
    }
    
    func main() {
       db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
       if err != nil {
           log.Fatalf("failed to connect to database: %v", err)
       }
    
       user := User{Name: "Hi"} // Length is 2, should violate the new constraint
       err = db.Create(&user).Error
       if err != nil {
           fmt.Printf("Expected error when inserting invalid data: %v\n", err)
       } else {
           fmt.Println("Unexpectedly inserted invalid data that should violate the new constraint")
       }
    
       user = User{Name: "Hello"} // Length is 5, should pass the new constraint
       err = db.Create(&user).Error
       if err != nil {
           fmt.Printf("Error when inserting valid data: %v\n", err)
       } else {
           fmt.Println("Successfully inserted valid data")
       }
    }
  4. Observe the Output:

    Unexpectedly inserted invalid data that should violate the new constraint
    Successfully inserted valid data

    This indicates that the check constraint was not updated in the database after modifying the model and running AutoMigrate again.


Expected Behavior:

Actual Behavior:


Possible Cause:


Environment:


Additional Context:


Workaround:

As a temporary workaround, manually drop the existing constraint before running AutoMigrate:

db.Migrator().DropConstraint(&User{}, "name_checker")
db.AutoMigrate(&User{})

This forces the constraint to be recreated with the updated definition.


Possible Solution:


Note on GORM Playground:

I attempted to create a GORM Playground Pull Request to reproduce this issue as per the contribution guidelines, but I encountered issues with the playground not functioning correctly. It seems there might be problems with the playground at the moment, so I was unable to use it to demonstrate the issue. Therefore, I have included a minimal reproducible example directly in this issue.

github-actions[bot] commented 1 month ago

The issue has been automatically marked as stale as it missing playground pull request link, which is important to help others understand your issue effectively and make sure the issue hasn't been fixed on latest master, checkout https://github.com/go-gorm/playground for details. it will be closed in 30 days if no further activity occurs. if you are asking question, please use the Question template, most likely your question already answered https://github.com/go-gorm/gorm/issues or described in the document https://gorm.ioSearch Before Asking