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() { |  | ||||||
| 	DB.Migrator().DropTable(&Animal{}) |  | ||||||
| 	DB.AutoMigrate(&Animal{}) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestNonStdPrimaryKeyAndDefaultValues(t *testing.T) { | func TestNonStdPrimaryKeyAndDefaultValues(t *testing.T) { | ||||||
|  | 	DB.Migrator().DropTable(&Animal{}) | ||||||
|  | 	if err := DB.AutoMigrate(&Animal{}); err != nil { | ||||||
|  | 		t.Fatalf("no error should happen when migrate but got %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jinzhu
						Jinzhu