diff --git a/field.go b/field.go index 7791d42a..452b7ba5 100644 --- a/field.go +++ b/field.go @@ -2,6 +2,7 @@ package gorm import ( "database/sql" + "errors" "reflect" "time" ) @@ -35,23 +36,28 @@ func (field *Field) IsTime() bool { return isTime } -func (field *Field) Set(value interface{}) (result bool) { - if field.Field.IsValid() && field.Field.CanAddr() { - result = true - if rvalue, ok := value.(reflect.Value); ok { - value = rvalue.Interface() - } +func (field *Field) Set(value interface{}) (err error) { + if !field.Field.IsValid() { + return errors.New("field value not valid") + } - if scanner, ok := field.Field.Addr().Interface().(sql.Scanner); ok { - scanner.Scan(value) - } else if reflect.TypeOf(value).ConvertibleTo(field.Field.Type()) { - field.Field.Set(reflect.ValueOf(value).Convert(field.Field.Type())) - } else { - result = false - } + if !field.Field.CanAddr() { + return errors.New("field value not addressable") } - if result { - field.IsBlank = isBlank(field.Field) + + if rvalue, ok := value.(reflect.Value); ok { + value = rvalue.Interface() } + + if scanner, ok := field.Field.Addr().Interface().(sql.Scanner); ok { + scanner.Scan(value) + } else if reflect.TypeOf(value).ConvertibleTo(field.Field.Type()) { + field.Field.Set(reflect.ValueOf(value).Convert(field.Field.Type())) + } else { + return errors.New("could not convert argument") + } + + field.IsBlank = isBlank(field.Field) + return } diff --git a/scope.go b/scope.go index 4183e1c2..47f347e7 100644 --- a/scope.go +++ b/scope.go @@ -129,19 +129,18 @@ func (scope *Scope) PrimaryKeyValue() interface{} { } // HasColumn to check if has column -func (scope *Scope) HasColumn(column string) bool { +func (scope *Scope) HasColumn(column string) (hasColumn bool) { clone := scope if scope.IndirectValue().Kind() == reflect.Slice { value := reflect.New(scope.IndirectValue().Type().Elem()).Interface() clone = scope.New(value) } - for _, field := range clone.Fields(false) { - if field.Name == column || field.DBName == column { - return true - } - } - return false + dbName := ToSnake(column) + + _, hasColumn = clone.Fields(false)[dbName] + + return } // FieldValueByName to get column's value and existence @@ -150,20 +149,21 @@ func (scope *Scope) FieldValueByName(name string) (interface{}, bool) { } // SetColumn to set the column's value -func (scope *Scope) SetColumn(column interface{}, value interface{}) bool { +func (scope *Scope) SetColumn(column interface{}, value interface{}) error { if field, ok := column.(*Field); ok { return field.Set(value) } else if str, ok := column.(string); ok { if scope.Value == nil { - return false + return errors.New("scope value must not be nil for string columns") } - for _, field := range scope.Fields() { - if field.Name == str || field.DBName == str { - return field.Set(value) - } + + dbName := ToSnake(str) + + if field, ok := scope.Fields()[dbName]; ok { + return field.Set(value) } } - return false + return errors.New("could not convert column to field") } // CallMethod invoke method with necessary argument