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 { | 			field.Set = func(ctx context.Context, value reflect.Value, v interface{}) error { | ||||||
| 				switch data := v.(type) { | 				switch data := v.(type) { | ||||||
| 				case **time.Time: | 				case **time.Time: | ||||||
| 					if data != nil { | 					if data != nil && *data != nil { | ||||||
| 						field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(*data)) | 						field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(*data)) | ||||||
| 					} | 					} | ||||||
| 				case time.Time: | 				case time.Time: | ||||||
| @ -882,14 +882,12 @@ func (field *Field) setupValuerAndSetter() { | |||||||
| 					reflectV := reflect.ValueOf(v) | 					reflectV := reflect.ValueOf(v) | ||||||
| 					if !reflectV.IsValid() { | 					if !reflectV.IsValid() { | ||||||
| 						field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem()) | 						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) { | 					} else if reflectV.Type().AssignableTo(field.FieldType) { | ||||||
| 						field.ReflectValueOf(ctx, value).Set(reflectV) | 						field.ReflectValueOf(ctx, value).Set(reflectV) | ||||||
| 					} else if reflectV.Kind() == reflect.Ptr { | 					} else if reflectV.Kind() == reflect.Ptr { | ||||||
| 						if reflectV.IsNil() || !reflectV.IsValid() { | 						return field.Set(ctx, value, reflectV.Elem().Interface()) | ||||||
| 							field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem()) |  | ||||||
| 						} else { |  | ||||||
| 							return field.Set(ctx, value, reflectV.Elem().Interface()) |  | ||||||
| 						} |  | ||||||
| 					} else { | 					} else { | ||||||
| 						fieldValue := field.ReflectValueOf(ctx, value) | 						fieldValue := field.ReflectValueOf(ctx, value) | ||||||
| 						if fieldValue.IsNil() { | 						if fieldValue.IsNil() { | ||||||
| @ -910,14 +908,12 @@ func (field *Field) setupValuerAndSetter() { | |||||||
| 					reflectV := reflect.ValueOf(v) | 					reflectV := reflect.ValueOf(v) | ||||||
| 					if !reflectV.IsValid() { | 					if !reflectV.IsValid() { | ||||||
| 						field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem()) | 						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) { | 					} else if reflectV.Type().AssignableTo(field.FieldType) { | ||||||
| 						field.ReflectValueOf(ctx, value).Set(reflectV) | 						field.ReflectValueOf(ctx, value).Set(reflectV) | ||||||
| 					} else if reflectV.Kind() == reflect.Ptr { | 					} else if reflectV.Kind() == reflect.Ptr { | ||||||
| 						if reflectV.IsNil() || !reflectV.IsValid() { | 						return field.Set(ctx, value, reflectV.Elem().Interface()) | ||||||
| 							field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem()) |  | ||||||
| 						} else { |  | ||||||
| 							return field.Set(ctx, value, reflectV.Elem().Interface()) |  | ||||||
| 						} |  | ||||||
| 					} else { | 					} else { | ||||||
| 						if valuer, ok := v.(driver.Valuer); ok { | 						if valuer, ok := v.(driver.Valuer); ok { | ||||||
| 							v, _ = valuer.Value() | 							v, _ = valuer.Value() | ||||||
|  | |||||||
| @ -4,7 +4,9 @@ import ( | |||||||
| 	"database/sql/driver" | 	"database/sql/driver" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"reflect" | ||||||
| 	"testing" | 	"testing" | ||||||
|  | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"gorm.io/gorm" | 	"gorm.io/gorm" | ||||||
| 	. "gorm.io/gorm/utils/tests" | 	. "gorm.io/gorm/utils/tests" | ||||||
| @ -104,10 +106,14 @@ func TestEmbeddedPointerTypeStruct(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	type Author struct { | 	type Author struct { | ||||||
| 		ID    string | 		ID          string | ||||||
| 		Name  string | 		Name        string | ||||||
| 		Email string | 		Email       string | ||||||
| 		Age   int | 		Age         int | ||||||
|  | 		Content     Content | ||||||
|  | 		ContentPtr  *Content | ||||||
|  | 		Birthday    time.Time | ||||||
|  | 		BirthdayPtr *time.Time | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	type HNPost struct { | 	type HNPost struct { | ||||||
| @ -135,6 +141,48 @@ func TestEmbeddedPointerTypeStruct(t *testing.T) { | |||||||
| 	if hnPost.Author != nil { | 	if hnPost.Author != nil { | ||||||
| 		t.Errorf("Expected to get back a nil Author but got: %v", hnPost.Author) | 		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 { | type Content struct { | ||||||
| @ -142,18 +190,26 @@ type Content struct { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c Content) Value() (driver.Value, error) { | 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 { | func (c *Content) Scan(src interface{}) error { | ||||||
| 	b, ok := src.([]byte) |  | ||||||
| 	if !ok { |  | ||||||
| 		return errors.New("Embedded.Scan byte assertion failed") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	var value Content | 	var value Content | ||||||
| 	if err := json.Unmarshal(b, &value); err != nil { | 	str, ok := src.(string) | ||||||
| 		return err | 	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 | 	*c = value | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 aclich
						aclich