Add support for custom column names

Fixes issue #26.
This commit is contained in:
Vytautas Šaltenis 2014-07-30 22:43:24 +03:00
parent 90106d82c5
commit eb26dcc597
6 changed files with 87 additions and 1 deletions

View File

@ -974,6 +974,26 @@ type Animal struct {
}
```
If your column names differ from the struct fields, you can specify them like this:
```go
type Animal struct { // animals
AnimalId int64 `gorm:"column:beast_id; primary_key:yes"`
Birthday time.Time `gorm:"column:day_of_the_beast"`
Age int64 `gorm:"column:age_of_the_beast"`
}
```
Note that if your primary key has a custom column name, you will still have to
specify `primary_key`, even if your struct field is named `Id`:
```go
type Foo struct {
Id int64 `gorm:"column:foo_id; primary_key:yes"`
}
```
## More examples with query chain
```go

View File

@ -41,6 +41,19 @@ func Query(scope *Scope) {
return
}
colToFieldMap := make(map[string]string)
if destType != nil && destType.Kind() == reflect.Struct {
for i := 0; i < destType.NumField(); i++ {
fieldName := destType.Field(i).Name
dbColumnName := ToSnake(fieldName)
settings := parseTagSetting(destType.Field(i).Tag.Get("gorm"))
if colName, ok := settings["COLUMN"]; ok && colName != "" {
dbColumnName = colName
}
colToFieldMap[dbColumnName] = fieldName
}
}
defer rows.Close()
for rows.Next() {
anyRecordFound = true
@ -52,7 +65,11 @@ func Query(scope *Scope) {
columns, _ := rows.Columns()
var values []interface{}
for _, value := range columns {
field := elem.FieldByName(SnakeToUpperCamel(strings.ToLower(value)))
fieldName, ok := colToFieldMap[value]
if !ok {
fieldName = SnakeToUpperCamel(strings.ToLower(value))
}
field := elem.FieldByName(fieldName)
if field.IsValid() {
values = append(values, field.Addr().Interface())
} else {

View File

@ -553,3 +553,40 @@ func BenchmarkRawSql(b *testing.B) {
db.Exec(delete_sql, id)
}
}
type MappedFields struct {
Id int64 `gorm:"column:mapped_id; primary_key:yes"`
Name string `gorm:"column:mapped_name"`
Date time.Time `gorm:"column:mapped_time"`
}
func TestMappedFields(t *testing.T) {
col := "mapped_name"
db := db.Model("")
scope := db.NewScope(&MappedFields{})
if !scope.Dialect().HasColumn(scope, "mapped_fields", col) {
t.Errorf("MappedFields should have column %s", col)
}
col = "mapped_id"
if scope.PrimaryKey() != col {
t.Errorf("MappedFields should have primary key %s, but got %q", col, scope.PrimaryKey())
}
expected := "foo"
mf := MappedFields{Id: 666, Name: expected, Date: time.Now()}
if !db.NewRecord(mf) || !db.NewRecord(&mf) {
t.Error("MappedFields should be new record before create")
}
if count := db.Save(&mf).RowsAffected; count != 1 {
t.Error("There should be one record be affected when create record")
}
var mfs []MappedFields
db.Table("mapped_fields").Find(&mfs)
if len(mfs) != 1 {
t.Errorf("Query from specified table")
}
if len(mfs) > 0 && mfs[0].Name != expected {
t.Errorf("Failed to query MappedFields, expected %q, got %q", expected, mfs[0].Name)
}
}

View File

@ -20,6 +20,7 @@ func runMigration() {
db.Exec("drop table animals")
db.Exec("drop table user_languages")
db.Exec("drop table languages")
db.Exec("drop table mapped_fields")
if err := db.CreateTable(&Animal{}).Error; err != nil {
panic(fmt.Sprintf("No error should happen when create table, but got %+v", err))
@ -37,6 +38,10 @@ func runMigration() {
panic(fmt.Sprintf("No error should happen when create table, but got %+v", err))
}
if err := db.CreateTable(MappedFields{}).Error; err != nil {
panic(fmt.Sprintf("No error should happen when create table, but got %+v", err))
}
if err := db.AutoMigrate(Address{}).Error; err != nil {
panic(fmt.Sprintf("No error should happen when create table, but got %+v", err))
}

View File

@ -258,6 +258,10 @@ func (scope *Scope) fieldFromStruct(fieldStruct reflect.StructField) *Field {
// Search for primary key tag identifier
settings := parseTagSetting(fieldStruct.Tag.Get("gorm"))
if colName, ok := settings["COLUMN"]; ok && colName != "" {
field.DBName = colName
}
if scope.PrimaryKey() == field.DBName {
field.IsPrimaryKey = true
}

View File

@ -109,6 +109,9 @@ func GetPrimaryKey(value interface{}) string {
settings := parseTagSetting(fieldStruct.Tag.Get("gorm"))
if _, ok := settings["PRIMARY_KEY"]; ok {
if colName, ok2 := settings["COLUMN"]; ok2 {
return colName
}
return fieldStruct.Name
} else if fieldStruct.Name == "Id" {
hasId = true