forked from mirror/gorm
Add AutoMigrate Support
This commit is contained in:
parent
5da8461161
commit
9b27735464
13
README.md
13
README.md
|
@ -14,6 +14,7 @@ Yet Another ORM library for Go, aims for developer friendly
|
|||
* Automatically CreatedAt, UpdatedAt
|
||||
* Soft Delete
|
||||
* Create/Drop table from struct
|
||||
* Automating Migrations
|
||||
* Dynamically set table name when search, create, update, delete...
|
||||
* Prevent SQL Injection
|
||||
* Goroutines friendly
|
||||
|
@ -97,6 +98,18 @@ db.CreateTable(User{})
|
|||
db.DropTable(User{})
|
||||
```
|
||||
|
||||
### Automating Migrations
|
||||
|
||||
Feel Free to update your struct, AutoMigrate will keep your database update to date.
|
||||
|
||||
FYI, AutoMigrate will only add new columns, won't change column's type or delete unused columns, to make sure gorm won't harm your data.
|
||||
|
||||
If table doesn't exist when AutoMigrate, it will run create table automatically.
|
||||
|
||||
```go
|
||||
db.AutoMigrate(User{})
|
||||
```
|
||||
|
||||
## Create
|
||||
|
||||
```go
|
||||
|
|
6
chain.go
6
chain.go
|
@ -236,17 +236,17 @@ func (s *Chain) Or(querystring interface{}, args ...interface{}) *Chain {
|
|||
}
|
||||
|
||||
func (s *Chain) CreateTable(value interface{}) *Chain {
|
||||
s.do(value).createTable().exec()
|
||||
s.do(value).createTable()
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Chain) DropTable(value interface{}) *Chain {
|
||||
s.do(value).dropTable().exec()
|
||||
s.do(value).dropTable()
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Chain) AutoMigrate(value interface{}) *Chain {
|
||||
s.do(value).autoMigrate().exec()
|
||||
s.do(value).autoMigrate()
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
26
do.go
26
do.go
|
@ -715,6 +715,7 @@ func (s *Do) createTable() *Do {
|
|||
s.tableName(),
|
||||
strings.Join(sqls, ","),
|
||||
)
|
||||
s.exec()
|
||||
return s
|
||||
}
|
||||
|
||||
|
@ -723,13 +724,32 @@ func (s *Do) dropTable() *Do {
|
|||
"DROP TABLE %v",
|
||||
s.tableName(),
|
||||
)
|
||||
s.exec()
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Do) autoMigrate() *Do {
|
||||
sql := fmt.Sprintf("SELECT column_name, data_type FROM information_schema.columns WHERE table_name = %v", s.tableName())
|
||||
for _, field := range s.model.fields("other") {
|
||||
s.sql = fmt.Sprintf(sql+"and column_name = %v", field.DbName)
|
||||
var table_name string
|
||||
sql := fmt.Sprintf("SELECT table_name FROM INFORMATION_SCHEMA.tables where table_name = %v", s.addToVars(s.tableName()))
|
||||
s.db.QueryRow(sql, s.sqlVars...).Scan(&table_name)
|
||||
s.sqlVars = []interface{}{}
|
||||
|
||||
// If table doesn't exist
|
||||
if len(table_name) == 0 {
|
||||
s.createTable()
|
||||
} else {
|
||||
for _, field := range s.model.fields("other") {
|
||||
var column_name, data_type string
|
||||
sql := fmt.Sprintf("SELECT column_name, data_type FROM information_schema.columns WHERE table_name = %v", s.addToVars(s.tableName()))
|
||||
s.db.QueryRow(fmt.Sprintf(sql+" and column_name = %v", s.addToVars(field.DbName)), s.sqlVars...).Scan(&column_name, &data_type)
|
||||
s.sqlVars = []interface{}{}
|
||||
|
||||
// If column doesn't exist
|
||||
if len(column_name) == 0 {
|
||||
s.sql = fmt.Sprintf("ALTER TABLE %v ADD %v %v", s.tableName(), field.DbName, field.SqlType)
|
||||
s.exec()
|
||||
}
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
39
gorm_test.go
39
gorm_test.go
|
@ -38,13 +38,12 @@ type CreditCard struct {
|
|||
}
|
||||
|
||||
type Email struct {
|
||||
Id int64
|
||||
UserId int64
|
||||
Email string
|
||||
Subscribed bool
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt time.Time
|
||||
Id int64
|
||||
UserId int64
|
||||
Email string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt time.Time
|
||||
}
|
||||
|
||||
type Address struct {
|
||||
|
@ -1236,6 +1235,32 @@ func TestTableName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
type BigEmail struct {
|
||||
Id int64
|
||||
UserId int64
|
||||
Email string
|
||||
UserAgent string
|
||||
RegisteredAt time.Time
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt time.Time
|
||||
}
|
||||
|
||||
func (b BigEmail) TableName() string {
|
||||
return "emails"
|
||||
}
|
||||
|
||||
func TestAutoMigration(t *testing.T) {
|
||||
db.AutoMigrate(Address{})
|
||||
if err := db.Table("emails").AutoMigrate(BigEmail{}).Error; err != nil {
|
||||
t.Errorf("Auto Migrate should not raise any error", err)
|
||||
}
|
||||
|
||||
db.Save(&BigEmail{Email: "jinzhu@example.org", UserAgent: "pc", RegisteredAt: time.Now()})
|
||||
|
||||
var big_email BigEmail
|
||||
db.First(&big_email, "user_agent = ?", "pc")
|
||||
if big_email.Email != "jinzhu@example.org" || big_email.UserAgent != "pc" || big_email.RegisteredAt.IsZero() {
|
||||
t.Error("Big Emails should be saved and fetched correctly")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue