mirror of https://github.com/go-gorm/gorm.git
fix: 🐛 embedded struct test failed with custom datatypes (#6311)
* fix: 🐛 embedded struct test failed with custom datatypes Fix the pointer embedded struct within custom datatypes and *time.time should be nil issue. * fix: 🐛 change test case to avoid mssql driver issue change test cases from bytes to string to avoid mssql driver issue
This commit is contained in:
parent
e61b98d696
commit
63534145fd
|
@ -846,7 +846,7 @@ func (field *Field) setupValuerAndSetter() {
|
|||
field.Set = func(ctx context.Context, value reflect.Value, v interface{}) error {
|
||||
switch data := v.(type) {
|
||||
case **time.Time:
|
||||
if data != nil {
|
||||
if data != nil && *data != nil {
|
||||
field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(*data))
|
||||
}
|
||||
case time.Time:
|
||||
|
@ -882,14 +882,12 @@ func (field *Field) setupValuerAndSetter() {
|
|||
reflectV := reflect.ValueOf(v)
|
||||
if !reflectV.IsValid() {
|
||||
field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
|
||||
} else if reflectV.Kind() == reflect.Ptr && reflectV.IsNil() {
|
||||
return
|
||||
} else if reflectV.Type().AssignableTo(field.FieldType) {
|
||||
field.ReflectValueOf(ctx, value).Set(reflectV)
|
||||
} else if reflectV.Kind() == reflect.Ptr {
|
||||
if reflectV.IsNil() || !reflectV.IsValid() {
|
||||
field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
|
||||
} else {
|
||||
return field.Set(ctx, value, reflectV.Elem().Interface())
|
||||
}
|
||||
return field.Set(ctx, value, reflectV.Elem().Interface())
|
||||
} else {
|
||||
fieldValue := field.ReflectValueOf(ctx, value)
|
||||
if fieldValue.IsNil() {
|
||||
|
@ -910,14 +908,12 @@ func (field *Field) setupValuerAndSetter() {
|
|||
reflectV := reflect.ValueOf(v)
|
||||
if !reflectV.IsValid() {
|
||||
field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
|
||||
} else if reflectV.Kind() == reflect.Ptr && reflectV.IsNil() {
|
||||
return
|
||||
} else if reflectV.Type().AssignableTo(field.FieldType) {
|
||||
field.ReflectValueOf(ctx, value).Set(reflectV)
|
||||
} else if reflectV.Kind() == reflect.Ptr {
|
||||
if reflectV.IsNil() || !reflectV.IsValid() {
|
||||
field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
|
||||
} else {
|
||||
return field.Set(ctx, value, reflectV.Elem().Interface())
|
||||
}
|
||||
return field.Set(ctx, value, reflectV.Elem().Interface())
|
||||
} else {
|
||||
if valuer, ok := v.(driver.Valuer); ok {
|
||||
v, _ = valuer.Value()
|
||||
|
|
|
@ -4,7 +4,9 @@ import (
|
|||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
. "gorm.io/gorm/utils/tests"
|
||||
|
@ -104,10 +106,14 @@ func TestEmbeddedPointerTypeStruct(t *testing.T) {
|
|||
}
|
||||
|
||||
type Author struct {
|
||||
ID string
|
||||
Name string
|
||||
Email string
|
||||
Age int
|
||||
ID string
|
||||
Name string
|
||||
Email string
|
||||
Age int
|
||||
Content Content
|
||||
ContentPtr *Content
|
||||
Birthday time.Time
|
||||
BirthdayPtr *time.Time
|
||||
}
|
||||
|
||||
type HNPost struct {
|
||||
|
@ -135,6 +141,48 @@ func TestEmbeddedPointerTypeStruct(t *testing.T) {
|
|||
if hnPost.Author != nil {
|
||||
t.Errorf("Expected to get back a nil Author but got: %v", hnPost.Author)
|
||||
}
|
||||
|
||||
now := time.Now().Round(time.Second)
|
||||
NewPost := HNPost{
|
||||
BasePost: &BasePost{Title: "embedded_pointer_type2"},
|
||||
Author: &Author{
|
||||
Name: "test",
|
||||
Content: Content{"test"},
|
||||
ContentPtr: nil,
|
||||
Birthday: now,
|
||||
BirthdayPtr: nil,
|
||||
},
|
||||
}
|
||||
DB.Create(&NewPost)
|
||||
|
||||
hnPost = HNPost{}
|
||||
if err := DB.First(&hnPost, "title = ?", NewPost.Title).Error; err != nil {
|
||||
t.Errorf("No error should happen when find embedded pointer type, but got %v", err)
|
||||
}
|
||||
|
||||
if hnPost.Title != NewPost.Title {
|
||||
t.Errorf("Should find correct value for embedded pointer type")
|
||||
}
|
||||
|
||||
if hnPost.Author.Name != NewPost.Author.Name {
|
||||
t.Errorf("Expected to get Author name %v but got: %v", NewPost.Author.Name, hnPost.Author.Name)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(NewPost.Author.Content, hnPost.Author.Content) {
|
||||
t.Errorf("Expected to get Author content %v but got: %v", NewPost.Author.Content, hnPost.Author.Content)
|
||||
}
|
||||
|
||||
if hnPost.Author.ContentPtr != nil {
|
||||
t.Errorf("Expected to get nil Author contentPtr but got: %v", hnPost.Author.ContentPtr)
|
||||
}
|
||||
|
||||
if NewPost.Author.Birthday.UnixMilli() != hnPost.Author.Birthday.UnixMilli() {
|
||||
t.Errorf("Expected to get Author birthday with %+v but got: %+v", NewPost.Author.Birthday, hnPost.Author.Birthday)
|
||||
}
|
||||
|
||||
if hnPost.Author.BirthdayPtr != nil {
|
||||
t.Errorf("Expected to get nil Author birthdayPtr but got: %+v", hnPost.Author.BirthdayPtr)
|
||||
}
|
||||
}
|
||||
|
||||
type Content struct {
|
||||
|
@ -142,18 +190,26 @@ type Content struct {
|
|||
}
|
||||
|
||||
func (c Content) Value() (driver.Value, error) {
|
||||
return json.Marshal(c)
|
||||
// mssql driver with issue on handling null bytes https://github.com/denisenkom/go-mssqldb/issues/530,
|
||||
b, err := json.Marshal(c)
|
||||
return string(b[:]), err
|
||||
}
|
||||
|
||||
func (c *Content) Scan(src interface{}) error {
|
||||
b, ok := src.([]byte)
|
||||
if !ok {
|
||||
return errors.New("Embedded.Scan byte assertion failed")
|
||||
}
|
||||
|
||||
var value Content
|
||||
if err := json.Unmarshal(b, &value); err != nil {
|
||||
return err
|
||||
str, ok := src.(string)
|
||||
if !ok {
|
||||
byt, ok := src.([]byte)
|
||||
if !ok {
|
||||
return errors.New("Embedded.Scan byte assertion failed")
|
||||
}
|
||||
if err := json.Unmarshal(byt, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := json.Unmarshal([]byte(str), &value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
*c = value
|
||||
|
|
Loading…
Reference in New Issue