mirror of https://github.com/go-gorm/gorm.git
Add tests for Columns
This commit is contained in:
parent
7c0de9199c
commit
7b6b9c4d22
|
@ -30,8 +30,5 @@ func (set Set) Build(builder Builder) {
|
||||||
|
|
||||||
// MergeClause merge assignments clauses
|
// MergeClause merge assignments clauses
|
||||||
func (set Set) MergeClause(clause *Clause) {
|
func (set Set) MergeClause(clause *Clause) {
|
||||||
if v, ok := clause.Expression.(Set); ok {
|
|
||||||
set = append(v, set...)
|
|
||||||
}
|
|
||||||
clause.Expression = set
|
clause.Expression = set
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestSet(t *testing.T) {
|
||||||
clause.Set([]clause.Assignment{{clause.PrimaryColumn, 1}}),
|
clause.Set([]clause.Assignment{{clause.PrimaryColumn, 1}}),
|
||||||
clause.Set([]clause.Assignment{{clause.Column{Name: "name"}, "jinzhu"}}),
|
clause.Set([]clause.Assignment{{clause.Column{Name: "name"}, "jinzhu"}}),
|
||||||
},
|
},
|
||||||
"UPDATE `users` SET `users`.`id`=?,`name`=?", []interface{}{1, "jinzhu"},
|
"UPDATE `users` SET `name`=?", []interface{}{"jinzhu"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,9 +116,11 @@ func (dialector Dialector) DataTypeOf(field *schema.Field) string {
|
||||||
return "double"
|
return "double"
|
||||||
case schema.String:
|
case schema.String:
|
||||||
size := field.Size
|
size := field.Size
|
||||||
if field.PrimaryKey && size == 0 {
|
if size == 0 {
|
||||||
|
if field.PrimaryKey || field.HasDefaultValue {
|
||||||
size = 256
|
size = 256
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if size >= 65536 && size <= int(math.Pow(2, 24)) {
|
if size >= 65536 && size <= int(math.Pow(2, 24)) {
|
||||||
return "mediumtext"
|
return "mediumtext"
|
||||||
|
|
|
@ -80,6 +80,25 @@ func (m Migrator) CreateIndex(value interface{}, name string) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Migrator) RenameIndex(value interface{}, oldName, newName string) error {
|
||||||
|
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
||||||
|
return m.DB.Exec(
|
||||||
|
"ALTER INDEX ? RENAME TO ?",
|
||||||
|
clause.Column{Name: oldName}, clause.Column{Name: newName},
|
||||||
|
).Error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Migrator) DropIndex(value interface{}, name string) error {
|
||||||
|
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
||||||
|
if idx := stmt.Schema.LookIndex(name); idx != nil {
|
||||||
|
name = idx.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.DB.Exec("DROP INDEX ?", clause.Column{Name: name}).Error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (m Migrator) HasTable(value interface{}) bool {
|
func (m Migrator) HasTable(value interface{}) bool {
|
||||||
var count int64
|
var count int64
|
||||||
m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
||||||
|
|
2
gorm.go
2
gorm.go
|
@ -66,7 +66,7 @@ func Open(dialector Dialector, config *Config) (db *DB, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.NowFunc == nil {
|
if config.NowFunc == nil {
|
||||||
config.NowFunc = func() time.Time { return time.Now().Local() }
|
config.NowFunc = func() time.Time { return time.Now().Local().Round(time.Second) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if dialector != nil {
|
if dialector != nil {
|
||||||
|
|
|
@ -28,7 +28,8 @@ const (
|
||||||
type LogLevel int
|
type LogLevel int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Error LogLevel = iota + 1
|
Silent LogLevel = iota + 1
|
||||||
|
Error
|
||||||
Warn
|
Warn
|
||||||
Info
|
Info
|
||||||
)
|
)
|
||||||
|
@ -129,7 +130,7 @@ func (l logger) Trace(ctx context.Context, begin time.Time, fc func() (string, i
|
||||||
if l.LogLevel > 0 {
|
if l.LogLevel > 0 {
|
||||||
elapsed := time.Now().Sub(begin)
|
elapsed := time.Now().Sub(begin)
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil && l.LogLevel >= Error:
|
||||||
sql, rows := fc()
|
sql, rows := fc()
|
||||||
l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
||||||
case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= Warn:
|
case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= Warn:
|
||||||
|
|
|
@ -47,25 +47,32 @@ func (m Migrator) DataTypeOf(field *schema.Field) string {
|
||||||
return m.Dialector.DataTypeOf(field)
|
return m.Dialector.DataTypeOf(field)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Migrator) FullDataTypeOf(field *schema.Field) string {
|
func (m Migrator) FullDataTypeOf(field *schema.Field) (expr clause.Expr) {
|
||||||
dataType := m.DataTypeOf(field)
|
expr.SQL = m.DataTypeOf(field)
|
||||||
|
|
||||||
if field.AutoIncrement {
|
if field.AutoIncrement {
|
||||||
dataType += " AUTO_INCREMENT"
|
expr.SQL += " AUTO_INCREMENT"
|
||||||
}
|
}
|
||||||
|
|
||||||
if field.NotNull {
|
if field.NotNull {
|
||||||
dataType += " NOT NULL"
|
expr.SQL += " NOT NULL"
|
||||||
}
|
}
|
||||||
|
|
||||||
if field.Unique {
|
if field.Unique {
|
||||||
dataType += " UNIQUE"
|
expr.SQL += " UNIQUE"
|
||||||
}
|
}
|
||||||
|
|
||||||
if field.HasDefaultValue {
|
if field.HasDefaultValue {
|
||||||
dataType += " DEFAULT " + field.DefaultValue
|
if field.DataType == schema.String {
|
||||||
|
defaultStmt := &gorm.Statement{Vars: []interface{}{field.DefaultValue}}
|
||||||
|
m.Dialector.BindVarTo(defaultStmt, defaultStmt, field.DefaultValue)
|
||||||
|
expr.SQL += " DEFAULT " + m.Dialector.Explain(defaultStmt.SQL.String(), field.DefaultValue)
|
||||||
|
} else {
|
||||||
|
expr.SQL += " DEFAULT " + field.DefaultValue
|
||||||
}
|
}
|
||||||
return dataType
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// AutoMigrate
|
// AutoMigrate
|
||||||
|
@ -138,7 +145,7 @@ func (m Migrator) CreateTable(values ...interface{}) error {
|
||||||
field := stmt.Schema.FieldsByDBName[dbName]
|
field := stmt.Schema.FieldsByDBName[dbName]
|
||||||
createTableSQL += fmt.Sprintf("? ?")
|
createTableSQL += fmt.Sprintf("? ?")
|
||||||
hasPrimaryKeyInDataType = hasPrimaryKeyInDataType || strings.Contains(strings.ToUpper(field.DBDataType), "PRIMARY KEY")
|
hasPrimaryKeyInDataType = hasPrimaryKeyInDataType || strings.Contains(strings.ToUpper(field.DBDataType), "PRIMARY KEY")
|
||||||
values = append(values, clause.Column{Name: dbName}, clause.Expr{SQL: m.FullDataTypeOf(field)})
|
values = append(values, clause.Column{Name: dbName}, m.FullDataTypeOf(field))
|
||||||
createTableSQL += ","
|
createTableSQL += ","
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +236,7 @@ func (m Migrator) AddColumn(value interface{}, field string) error {
|
||||||
if field := stmt.Schema.LookUpField(field); field != nil {
|
if field := stmt.Schema.LookUpField(field); field != nil {
|
||||||
return m.DB.Exec(
|
return m.DB.Exec(
|
||||||
"ALTER TABLE ? ADD ? ?",
|
"ALTER TABLE ? ADD ? ?",
|
||||||
clause.Table{Name: stmt.Table}, clause.Column{Name: field.DBName}, clause.Expr{SQL: m.FullDataTypeOf(field)},
|
clause.Table{Name: stmt.Table}, clause.Column{Name: field.DBName}, m.FullDataTypeOf(field),
|
||||||
).Error
|
).Error
|
||||||
}
|
}
|
||||||
return fmt.Errorf("failed to look up field with name: %s", field)
|
return fmt.Errorf("failed to look up field with name: %s", field)
|
||||||
|
|
|
@ -30,44 +30,86 @@ func TestMigrate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIndexes(t *testing.T) {
|
func TestIndexes(t *testing.T) {
|
||||||
type User struct {
|
type IndexStruct struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Name string `gorm:"index"`
|
Name string `gorm:"size:255;index"`
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := DB.Migrator().CreateIndex(&User{}, "Name"); err != nil {
|
DB.Migrator().DropTable(&IndexStruct{})
|
||||||
|
DB.AutoMigrate(&IndexStruct{})
|
||||||
|
|
||||||
|
if err := DB.Migrator().DropIndex(&IndexStruct{}, "Name"); err != nil {
|
||||||
|
t.Errorf("Failed to drop index for user's name, got err %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Migrator().CreateIndex(&IndexStruct{}, "Name"); err != nil {
|
||||||
t.Errorf("Got error when tried to create index: %+v", err)
|
t.Errorf("Got error when tried to create index: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !DB.Migrator().HasIndex(&User{}, "Name") {
|
if !DB.Migrator().HasIndex(&IndexStruct{}, "Name") {
|
||||||
t.Errorf("Failed to find index for user's name")
|
t.Errorf("Failed to find index for user's name")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := DB.Migrator().DropIndex(&User{}, "Name"); err != nil {
|
if err := DB.Migrator().DropIndex(&IndexStruct{}, "Name"); err != nil {
|
||||||
t.Errorf("Failed to drop index for user's name, got err %v", err)
|
t.Errorf("Failed to drop index for user's name, got err %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if DB.Migrator().HasIndex(&User{}, "Name") {
|
if DB.Migrator().HasIndex(&IndexStruct{}, "Name") {
|
||||||
t.Errorf("Should not find index for user's name after delete")
|
t.Errorf("Should not find index for user's name after delete")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := DB.Migrator().CreateIndex(&User{}, "Name"); err != nil {
|
if err := DB.Migrator().CreateIndex(&IndexStruct{}, "Name"); err != nil {
|
||||||
t.Errorf("Got error when tried to create index: %+v", err)
|
t.Errorf("Got error when tried to create index: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := DB.Migrator().RenameIndex(&User{}, "idx_users_name", "idx_users_name_1"); err != nil {
|
if err := DB.Migrator().RenameIndex(&IndexStruct{}, "idx_index_structs_name", "idx_users_name_1"); err != nil {
|
||||||
t.Errorf("no error should happen when rename index, but got %v", err)
|
t.Errorf("no error should happen when rename index, but got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !DB.Migrator().HasIndex(&User{}, "idx_users_name_1") {
|
if !DB.Migrator().HasIndex(&IndexStruct{}, "idx_users_name_1") {
|
||||||
t.Errorf("Should find index for user's name after rename")
|
t.Errorf("Should find index for user's name after rename")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := DB.Migrator().DropIndex(&User{}, "idx_users_name_1"); err != nil {
|
if err := DB.Migrator().DropIndex(&IndexStruct{}, "idx_users_name_1"); err != nil {
|
||||||
t.Errorf("Failed to drop index for user's name, got err %v", err)
|
t.Errorf("Failed to drop index for user's name, got err %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if DB.Migrator().HasIndex(&User{}, "idx_users_name_1") {
|
if DB.Migrator().HasIndex(&IndexStruct{}, "idx_users_name_1") {
|
||||||
t.Errorf("Should not find index for user's name after delete")
|
t.Errorf("Should not find index for user's name after delete")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestColumns(t *testing.T) {
|
||||||
|
type ColumnStruct struct {
|
||||||
|
gorm.Model
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Migrator().DropTable(&ColumnStruct{})
|
||||||
|
|
||||||
|
if err := DB.AutoMigrate(&ColumnStruct{}); err != nil {
|
||||||
|
t.Errorf("Failed to migrate, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type NewColumnStruct struct {
|
||||||
|
gorm.Model
|
||||||
|
Name string
|
||||||
|
NewName string
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("column_structs").Migrator().AddColumn(&NewColumnStruct{}, "NewName"); err != nil {
|
||||||
|
t.Errorf("Failed to add column, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !DB.Table("column_structs").Migrator().HasColumn(&NewColumnStruct{}, "NewName") {
|
||||||
|
t.Errorf("Failed to find added column")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.Table("column_structs").Migrator().DropColumn(&NewColumnStruct{}, "NewName"); err != nil {
|
||||||
|
t.Errorf("Failed to add column, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if DB.Table("column_structs").Migrator().HasColumn(&NewColumnStruct{}, "NewName") {
|
||||||
|
t.Errorf("Found deleted column")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,18 +11,18 @@ type Animal struct {
|
||||||
Counter uint64 `gorm:"primary_key:yes"`
|
Counter uint64 `gorm:"primary_key:yes"`
|
||||||
Name string `gorm:"DEFAULT:'galeone'"`
|
Name string `gorm:"DEFAULT:'galeone'"`
|
||||||
From string //test reserved sql keyword as field name
|
From string //test reserved sql keyword as field name
|
||||||
Age time.Time `gorm:"DEFAULT:current_timestamp"`
|
Age *time.Time
|
||||||
unexported string // unexported value
|
unexported string // unexported value
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func TestNonStdPrimaryKeyAndDefaultValues(t *testing.T) {
|
||||||
DB.Migrator().DropTable(&Animal{})
|
DB.Migrator().DropTable(&Animal{})
|
||||||
DB.AutoMigrate(&Animal{})
|
if err := DB.AutoMigrate(&Animal{}); err != nil {
|
||||||
|
t.Fatalf("no error should happen when migrate but got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNonStdPrimaryKeyAndDefaultValues(t *testing.T) {
|
|
||||||
animal := Animal{Name: "Ferdinand"}
|
animal := Animal{Name: "Ferdinand"}
|
||||||
DB.Save(&animal)
|
DB.Save(&animal)
|
||||||
updatedAt1 := animal.UpdatedAt
|
updatedAt1 := animal.UpdatedAt
|
||||||
|
|
|
@ -61,7 +61,7 @@ func OpenTestConnection() (db *gorm.DB, err error) {
|
||||||
if debug := os.Getenv("DEBUG"); debug == "true" {
|
if debug := os.Getenv("DEBUG"); debug == "true" {
|
||||||
db.Logger.LogMode(logger.Info)
|
db.Logger.LogMode(logger.Info)
|
||||||
} else if debug == "false" {
|
} else if debug == "false" {
|
||||||
db.Logger.LogMode(logger.Error)
|
db.Logger.LogMode(logger.Silent)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -26,7 +26,7 @@ type Config struct {
|
||||||
|
|
||||||
func GetUser(name string, config Config) *User {
|
func GetUser(name string, config Config) *User {
|
||||||
var (
|
var (
|
||||||
birthday = time.Now()
|
birthday = time.Now().Round(time.Second)
|
||||||
user = User{
|
user = User{
|
||||||
Name: name,
|
Name: name,
|
||||||
Age: 18,
|
Age: 18,
|
||||||
|
|
Loading…
Reference in New Issue