From c2e863f0372d3ba639953fc55f1153c38885d661 Mon Sep 17 00:00:00 2001 From: peihexian Date: Wed, 8 May 2019 11:26:36 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3Conversion=E6=8E=A5=E5=8F=A3T?= =?UTF-8?q?oDB()=20([]byte,=20error)=E6=96=B9=E6=B3=95=E8=BF=94=E5=9B=9E*T?= =?UTF-8?q?ype=E5=80=BC=E4=B8=BAnil=E6=97=B6,=E6=95=B0=E6=8D=AE=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=B8=BA[]byte(nil)=E7=9A=84bug,=E8=A7=A3=E5=86=B3*Ty?= =?UTF-8?q?pe=E5=80=BC=E4=B8=BAnil=E6=97=B6=E6=8F=92=E5=85=A5=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=8F=98=E4=B8=BA""=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/statements/values.go | 3 + session_convert.go | 135 ++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/internal/statements/values.go b/internal/statements/values.go index b545a605..0ab174d6 100644 --- a/internal/statements/values.go +++ b/internal/statements/values.go @@ -44,6 +44,9 @@ func (statement *Statement) Value2Interface(col *schemas.Column, fieldValue refl if col.SQLType.IsBlob() { return data, nil } + if nil == data { + return nil, nil + } return string(data), nil } diff --git a/session_convert.go b/session_convert.go index a6839947..0707d677 100644 --- a/session_convert.go +++ b/session_convert.go @@ -527,3 +527,138 @@ func (session *Session) bytes2Value(col *schemas.Column, fieldValue *reflect.Val return nil } +<<<<<<< HEAD +======= + +// convert a field value of a struct to interface for put into db +func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Value) (interface{}, error) { + if fieldValue.CanAddr() { + if fieldConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok { + data, err := fieldConvert.ToDB() + if err != nil { + return 0, err + } + if col.SQLType.IsBlob() { + return data, nil + } + return string(data), nil + } + } + + if fieldConvert, ok := fieldValue.Interface().(core.Conversion); ok { + data, err := fieldConvert.ToDB() + if err != nil { + return 0, err + } + if col.SQLType.IsBlob() { + return data, nil + } + if nil==data { + return nil,nil + } + return string(data), nil + } + + fieldType := fieldValue.Type() + k := fieldType.Kind() + if k == reflect.Ptr { + if fieldValue.IsNil() { + return nil, nil + } else if !fieldValue.IsValid() { + session.engine.logger.Warn("the field[", col.FieldName, "] is invalid") + return nil, nil + } else { + // !nashtsai! deference pointer type to instance type + fieldValue = fieldValue.Elem() + fieldType = fieldValue.Type() + k = fieldType.Kind() + } + } + + switch k { + case reflect.Bool: + return fieldValue.Bool(), nil + case reflect.String: + return fieldValue.String(), nil + case reflect.Struct: + if fieldType.ConvertibleTo(core.TimeType) { + t := fieldValue.Convert(core.TimeType).Interface().(time.Time) + tf := session.engine.formatColTime(col, t) + return tf, nil + } + + if !col.SQLType.IsJson() { + // !! 增加支持driver.Valuer接口的结构,如sql.NullString + if v, ok := fieldValue.Interface().(driver.Valuer); ok { + return v.Value() + } + + fieldTable, err := session.engine.autoMapType(fieldValue) + if err != nil { + return nil, err + } + if len(fieldTable.PrimaryKeys) == 1 { + pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumns()[0].FieldName) + return pkField.Interface(), nil + } + return 0, fmt.Errorf("no primary key for col %v", col.Name) + } + + if col.SQLType.IsText() { + bytes, err := DefaultJSONHandler.Marshal(fieldValue.Interface()) + if err != nil { + session.engine.logger.Error(err) + return 0, err + } + return string(bytes), nil + } else if col.SQLType.IsBlob() { + bytes, err := DefaultJSONHandler.Marshal(fieldValue.Interface()) + if err != nil { + session.engine.logger.Error(err) + return 0, err + } + return bytes, nil + } + return nil, fmt.Errorf("Unsupported type %v", fieldValue.Type()) + case reflect.Complex64, reflect.Complex128: + bytes, err := DefaultJSONHandler.Marshal(fieldValue.Interface()) + if err != nil { + session.engine.logger.Error(err) + return 0, err + } + return string(bytes), nil + case reflect.Array, reflect.Slice, reflect.Map: + if !fieldValue.IsValid() { + return fieldValue.Interface(), nil + } + + if col.SQLType.IsText() { + bytes, err := DefaultJSONHandler.Marshal(fieldValue.Interface()) + if err != nil { + session.engine.logger.Error(err) + return 0, err + } + return string(bytes), nil + } else if col.SQLType.IsBlob() { + var bytes []byte + var err error + if (k == reflect.Array || k == reflect.Slice) && + (fieldValue.Type().Elem().Kind() == reflect.Uint8) { + bytes = fieldValue.Bytes() + } else { + bytes, err = DefaultJSONHandler.Marshal(fieldValue.Interface()) + if err != nil { + session.engine.logger.Error(err) + return 0, err + } + } + return bytes, nil + } + return nil, ErrUnSupportedType + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return int64(fieldValue.Uint()), nil + default: + return fieldValue.Interface(), nil + } +} +>>>>>>> 解决Conversion接口ToDB() ([]byte, error)方法返回*Type值为nil时,数据类型为[]byte(nil)的bug,解决*Type值为nil时插入数据变为""的bug