mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
improve data converting for package gdb, drivers/pgsql
This commit is contained in:
@ -37,10 +37,10 @@ func Test_Func_ConvertDataForRecord(t *testing.T) {
|
||||
}
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c := &gdb.Core{}
|
||||
m := c.ConvertDataForRecord(nil, new(Test))
|
||||
m, err := c.ConvertDataForRecord(nil, new(Test))
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(m), 1)
|
||||
t.AssertNE(m["reset_password_token_at"], nil)
|
||||
t.Assert(m["reset_password_token_at"], new(mysql.NullTime))
|
||||
t.Assert(m["reset_password_token_at"], nil)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -170,7 +170,7 @@ type DB interface {
|
||||
GetChars() (charLeft string, charRight string) // See Core.GetChars.
|
||||
Tables(ctx context.Context, schema ...string) (tables []string, err error) // See Core.Tables.
|
||||
TableFields(ctx context.Context, table string, schema ...string) (map[string]*TableField, error) // See Core.TableFields.
|
||||
ConvertDataForRecord(ctx context.Context, data interface{}) map[string]interface{} // See Core.ConvertDataForRecord
|
||||
ConvertDataForRecord(ctx context.Context, data interface{}) (map[string]interface{}, error) // See Core.ConvertDataForRecord
|
||||
FilteredLink() string // FilteredLink is used for filtering sensitive information in `Link` configuration before output it to tracing server.
|
||||
}
|
||||
|
||||
|
||||
@ -552,7 +552,7 @@ func (c *Core) DoUpdate(ctx context.Context, link Link, table string, data inter
|
||||
case reflect.Map, reflect.Struct:
|
||||
var (
|
||||
fields []string
|
||||
dataMap = c.db.ConvertDataForRecord(ctx, data)
|
||||
dataMap map[string]interface{}
|
||||
counterHandler = func(column string, counter Counter) {
|
||||
if counter.Value != 0 {
|
||||
column = c.QuoteWord(column)
|
||||
@ -570,7 +570,10 @@ func (c *Core) DoUpdate(ctx context.Context, link Link, table string, data inter
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
dataMap, err = c.db.ConvertDataForRecord(ctx, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range dataMap {
|
||||
switch value := v.(type) {
|
||||
case *Counter:
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gbinary"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/internal/json"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
@ -27,27 +28,33 @@ import (
|
||||
//
|
||||
// The parameter `value` should be type of *map/map/*struct/struct.
|
||||
// It supports embedded struct definition for struct.
|
||||
func (c *Core) ConvertDataForRecord(ctx context.Context, value interface{}) map[string]interface{} {
|
||||
var data = DataToMapDeep(value)
|
||||
func (c *Core) ConvertDataForRecord(ctx context.Context, value interface{}) (map[string]interface{}, error) {
|
||||
var (
|
||||
err error
|
||||
data = DataToMapDeep(value)
|
||||
)
|
||||
for k, v := range data {
|
||||
data[k] = c.ConvertDataForRecordValue(ctx, v)
|
||||
data[k], err = c.ConvertDataForRecordValue(ctx, v)
|
||||
if err != nil {
|
||||
return nil, gerror.Wrapf(err, `ConvertDataForRecordValue failed for value: %#v`, v)
|
||||
}
|
||||
}
|
||||
return data
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (c *Core) ConvertDataForRecordValue(ctx context.Context, value interface{}) interface{} {
|
||||
func (c *Core) ConvertDataForRecordValue(ctx context.Context, value interface{}) (interface{}, error) {
|
||||
var (
|
||||
err error
|
||||
convertedValue interface{}
|
||||
convertedValue = value
|
||||
)
|
||||
// If `value` implements interface `driver.Valuer`, it then uses the interface for value converting.
|
||||
if valuer, ok := value.(driver.Valuer); ok {
|
||||
if convertedValue, err = valuer.Value(); err != nil {
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return convertedValue
|
||||
return convertedValue, nil
|
||||
}
|
||||
// Default value converting.
|
||||
var (
|
||||
@ -63,7 +70,10 @@ func (c *Core) ConvertDataForRecordValue(ctx context.Context, value interface{})
|
||||
// It should ignore the bytes type.
|
||||
if _, ok := value.([]byte); !ok {
|
||||
// Convert the value to JSON.
|
||||
convertedValue, _ = json.Marshal(value)
|
||||
convertedValue, err = json.Marshal(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
@ -97,11 +107,14 @@ func (c *Core) ConvertDataForRecordValue(ctx context.Context, value interface{})
|
||||
convertedValue = s.String()
|
||||
} else {
|
||||
// Convert the value to JSON.
|
||||
convertedValue, _ = json.Marshal(value)
|
||||
convertedValue, err = json.Marshal(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return convertedValue
|
||||
return convertedValue, nil
|
||||
}
|
||||
|
||||
// convertFieldValueToLocalValue automatically checks and converts field value from database type
|
||||
|
||||
@ -40,6 +40,7 @@ func (m *Model) Batch(batch int) *Model {
|
||||
// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"}).
|
||||
func (m *Model) Data(data ...interface{}) *Model {
|
||||
var (
|
||||
err error
|
||||
ctx = m.GetCtx()
|
||||
model = m.getModel()
|
||||
)
|
||||
@ -87,7 +88,10 @@ func (m *Model) Data(data ...interface{}) *Model {
|
||||
}
|
||||
list := make(List, reflectInfo.OriginValue.Len())
|
||||
for i := 0; i < reflectInfo.OriginValue.Len(); i++ {
|
||||
list[i] = m.db.ConvertDataForRecord(ctx, reflectInfo.OriginValue.Index(i).Interface())
|
||||
list[i], err = m.db.ConvertDataForRecord(ctx, reflectInfo.OriginValue.Index(i).Interface())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
model.data = list
|
||||
|
||||
@ -104,15 +108,24 @@ func (m *Model) Data(data ...interface{}) *Model {
|
||||
list = make(List, len(array))
|
||||
)
|
||||
for i := 0; i < len(array); i++ {
|
||||
list[i] = m.db.ConvertDataForRecord(ctx, array[i])
|
||||
list[i], err = m.db.ConvertDataForRecord(ctx, array[i])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
model.data = list
|
||||
} else {
|
||||
model.data = m.db.ConvertDataForRecord(ctx, data[0])
|
||||
model.data, err = m.db.ConvertDataForRecord(ctx, data[0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
model.data = m.db.ConvertDataForRecord(ctx, data[0])
|
||||
model.data, err = m.db.ConvertDataForRecord(ctx, data[0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
default:
|
||||
model.data = data[0]
|
||||
@ -255,11 +268,18 @@ func (m *Model) doInsertWithOption(ctx context.Context, insertOption int) (resul
|
||||
case List:
|
||||
list = value
|
||||
for i, v := range list {
|
||||
list[i] = m.db.ConvertDataForRecord(ctx, v)
|
||||
list[i], err = m.db.ConvertDataForRecord(ctx, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
case Map:
|
||||
list = List{m.db.ConvertDataForRecord(ctx, value)}
|
||||
var listItem map[string]interface{}
|
||||
if listItem, err = m.db.ConvertDataForRecord(ctx, value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list = List{listItem}
|
||||
|
||||
default:
|
||||
reflectInfo := reflection.OriginValueAndKind(newData)
|
||||
@ -268,21 +288,32 @@ func (m *Model) doInsertWithOption(ctx context.Context, insertOption int) (resul
|
||||
case reflect.Slice, reflect.Array:
|
||||
list = make(List, reflectInfo.OriginValue.Len())
|
||||
for i := 0; i < reflectInfo.OriginValue.Len(); i++ {
|
||||
list[i] = m.db.ConvertDataForRecord(ctx, reflectInfo.OriginValue.Index(i).Interface())
|
||||
list[i], err = m.db.ConvertDataForRecord(ctx, reflectInfo.OriginValue.Index(i).Interface())
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
list = List{m.db.ConvertDataForRecord(ctx, value)}
|
||||
var listItem map[string]interface{}
|
||||
if listItem, err = m.db.ConvertDataForRecord(ctx, value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list = List{listItem}
|
||||
|
||||
case reflect.Struct:
|
||||
if v, ok := value.(iInterfaces); ok {
|
||||
array := v.Interfaces()
|
||||
list = make(List, len(array))
|
||||
for i := 0; i < len(array); i++ {
|
||||
list[i] = m.db.ConvertDataForRecord(ctx, array[i])
|
||||
list[i], err = m.db.ConvertDataForRecord(ctx, array[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
list = List{m.db.ConvertDataForRecord(ctx, value)}
|
||||
var listItem map[string]interface{}
|
||||
if listItem, err = m.db.ConvertDataForRecord(ctx, value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list = List{listItem}
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@ -51,7 +51,11 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro
|
||||
)
|
||||
switch reflectInfo.OriginKind {
|
||||
case reflect.Map, reflect.Struct:
|
||||
dataMap := m.db.ConvertDataForRecord(ctx, m.data)
|
||||
var dataMap map[string]interface{}
|
||||
dataMap, err = m.db.ConvertDataForRecord(ctx, m.data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Automatically update the record updating time.
|
||||
if !m.unscoped && fieldNameUpdate != "" {
|
||||
dataMap[fieldNameUpdate] = gtime.Now().String()
|
||||
|
||||
Reference in New Issue
Block a user