diff --git a/helpers.go b/helpers.go index 8c0f7574..b80d1e53 100644 --- a/helpers.go +++ b/helpers.go @@ -156,6 +156,17 @@ func isZero(k interface{}) bool { return false } +func isZeroValue(v reflect.Value) bool { + if isZero(v.Interface()) { + return true + } + switch v.Kind() { + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return v.IsNil() + } + return false +} + func isStructZero(v reflect.Value) bool { if !v.IsValid() { return true @@ -414,7 +425,7 @@ func genCols(table *core.Table, session *Session, bean interface{}, useCol bool, // !evalphobia! set fieldValue as nil when column is nullable and zero-value if _, ok := getFlagForColumn(session.Statement.nullableMap, col); ok { - if col.Nullable && isZero(fieldValue.Interface()) { + if col.Nullable && isZeroValue(fieldValue) { var nilValue *int fieldValue = reflect.ValueOf(nilValue) } diff --git a/types_test.go b/types_test.go index aadf5f69..222c4f80 100644 --- a/types_test.go +++ b/types_test.go @@ -134,13 +134,39 @@ func (s *SliceType) ToDB() ([]byte, error) { return json.Marshal(s) } +type Nullable struct { + Data string +} + +func (s *Nullable) FromDB(data []byte) error { + if data == nil { + return nil + } + + *s = Nullable{ + Data: string(data), + } + + return nil +} + +func (s *Nullable) ToDB() ([]byte, error) { + if s == nil { + return nil, nil + } + + return []byte(s.Data), nil +} + type ConvStruct struct { - Conv ConvString - Conv2 *ConvString - Cfg1 ConvConfig - Cfg2 *ConvConfig `xorm:"TEXT"` - Cfg3 core.Conversion `xorm:"BLOB"` - Slice SliceType + Conv ConvString + Conv2 *ConvString + Cfg1 ConvConfig + Cfg2 *ConvConfig `xorm:"TEXT"` + Cfg3 core.Conversion `xorm:"BLOB"` + Slice SliceType + Nullable1 *Nullable `xorm:"null"` + Nullable2 *Nullable `xorm:"null"` } func (c *ConvStruct) BeforeSet(name string, cell Cell) { @@ -163,8 +189,10 @@ func TestConversion(t *testing.T) { c.Cfg2 = &ConvConfig{"xx", 2} c.Cfg3 = &ConvConfig{"zz", 3} c.Slice = []*ConvConfig{{"yy", 4}, {"ff", 5}} + c.Nullable1 = &Nullable{Data: "test"} + c.Nullable2 = nil - _, err := testEngine.Insert(c) + _, err := testEngine.Nullable("nullable2").Insert(c) assert.NoError(t, err) c1 := new(ConvStruct) @@ -182,6 +210,9 @@ func TestConversion(t *testing.T) { assert.EqualValues(t, 2, len(c1.Slice)) assert.EqualValues(t, *c.Slice[0], *c1.Slice[0]) assert.EqualValues(t, *c.Slice[1], *c1.Slice[1]) + assert.NotNil(t, c1.Nullable1) + assert.Equal(t, c1.Nullable1.Data, "test") + assert.Nil(t, c1.Nullable2) } type MyInt int