Add AutoMigrate Support

This commit is contained in:
Jinzhu 2013-11-07 11:42:36 +08:00
parent 5da8461161
commit 9b27735464
4 changed files with 71 additions and 13 deletions

View File

@ -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

View File

@ -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
View File

@ -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
}

View File

@ -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")
}
}