Fix pool manager

This commit is contained in:
Jinzhu 2022-02-15 15:08:43 +08:00
parent 744c91c9a7
commit 20abf83a21
2 changed files with 57 additions and 45 deletions

10
scan.go
View File

@ -55,15 +55,13 @@ func (db *DB) scanIntoStruct(sch *schema.Schema, rows *sql.Rows, reflectValue re
if sch == nil { if sch == nil {
values[idx] = reflectValue.Interface() values[idx] = reflectValue.Interface()
} else if field := sch.LookUpField(column); field != nil && field.Readable { } else if field := sch.LookUpField(column); field != nil && field.Readable {
fieldValue := field.NewValuePool.Get() values[idx] = field.NewValuePool.Get()
values[idx] = &fieldValue defer field.NewValuePool.Put(values[idx])
defer field.NewValuePool.Put(fieldValue)
} else if names := strings.Split(column, "__"); len(names) > 1 { } else if names := strings.Split(column, "__"); len(names) > 1 {
if rel, ok := sch.Relationships.Relations[names[0]]; ok { if rel, ok := sch.Relationships.Relations[names[0]]; ok {
if field := rel.FieldSchema.LookUpField(strings.Join(names[1:], "__")); field != nil && field.Readable { if field := rel.FieldSchema.LookUpField(strings.Join(names[1:], "__")); field != nil && field.Readable {
fieldValue := field.NewValuePool.Get() values[idx] = field.NewValuePool.Get()
values[idx] = &fieldValue defer field.NewValuePool.Put(values[idx])
defer field.NewValuePool.Put(fieldValue)
continue continue
} }
} }

View File

@ -417,36 +417,43 @@ var (
stringPool = &sync.Pool{ stringPool = &sync.Pool{
New: func() interface{} { New: func() interface{} {
var v string var v string
return &v ptrV := &v
return &ptrV
}, },
} }
intPool = &sync.Pool{ intPool = &sync.Pool{
New: func() interface{} { New: func() interface{} {
var v int64 var v int64
return &v ptrV := &v
return &ptrV
}, },
} }
uintPool = &sync.Pool{ uintPool = &sync.Pool{
New: func() interface{} { New: func() interface{} {
var v uint64 var v uint64
return &v ptrV := &v
return &ptrV
}, },
} }
floatPool = &sync.Pool{ floatPool = &sync.Pool{
New: func() interface{} { New: func() interface{} {
var v float64 var v float64
return &v ptrV := &v
return &ptrV
}, },
} }
boolPool = &sync.Pool{ boolPool = &sync.Pool{
New: func() interface{} { New: func() interface{} {
var v bool var v bool
return &v ptrV := &v
return &ptrV
}, },
} }
timePool = &sync.Pool{ timePool = &sync.Pool{
New: func() interface{} { New: func() interface{} {
return &time.Time{} var v time.Time
ptrV := &v
return &ptrV
}, },
} }
) )
@ -454,6 +461,7 @@ var (
// create valuer, setter when parse struct // create valuer, setter when parse struct
func (field *Field) setupValuerAndSetter() { func (field *Field) setupValuerAndSetter() {
// Setup NewValuePool // Setup NewValuePool
if _, ok := reflect.New(field.IndirectFieldType).Interface().(sql.Scanner); !ok {
switch field.IndirectFieldType.Kind() { switch field.IndirectFieldType.Kind() {
case reflect.String: case reflect.String:
field.NewValuePool = stringPool field.NewValuePool = stringPool
@ -469,6 +477,9 @@ func (field *Field) setupValuerAndSetter() {
if field.IndirectFieldType == TimeReflectType { if field.IndirectFieldType == TimeReflectType {
field.NewValuePool = timePool field.NewValuePool = timePool
} }
}
}
if field.NewValuePool == nil { if field.NewValuePool == nil {
field.NewValuePool = fieldNewValuePool{ field.NewValuePool = fieldNewValuePool{
getter: func() interface{} { getter: func() interface{} {
@ -477,7 +488,6 @@ func (field *Field) setupValuerAndSetter() {
putter: func(interface{}) {}, putter: func(interface{}) {},
} }
} }
}
// ValueOf returns field's value and if it is zero // ValueOf returns field's value and if it is zero
field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) { field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) {
@ -580,14 +590,12 @@ func (field *Field) setupValuerAndSetter() {
case reflect.Bool: case reflect.Bool:
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 **bool:
if data != nil && *data != nil {
field.ReflectValueOf(ctx, value).SetBool(**data)
}
case bool: case bool:
field.ReflectValueOf(ctx, value).SetBool(data) field.ReflectValueOf(ctx, value).SetBool(data)
case **bool:
if data != nil {
field.ReflectValueOf(ctx, value).SetBool(**data)
} else {
field.ReflectValueOf(ctx, value).SetBool(false)
}
case int64: case int64:
field.ReflectValueOf(ctx, value).SetBool(data > 0) field.ReflectValueOf(ctx, value).SetBool(data > 0)
case string: case string:
@ -602,7 +610,7 @@ func (field *Field) setupValuerAndSetter() {
field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) { field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
switch data := v.(type) { switch data := v.(type) {
case **int64: case **int64:
if data != nil { if data != nil && *data != nil {
field.ReflectValueOf(ctx, value).SetInt(**data) field.ReflectValueOf(ctx, value).SetInt(**data)
} }
case int64: case int64:
@ -666,7 +674,7 @@ func (field *Field) setupValuerAndSetter() {
field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) { field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
switch data := v.(type) { switch data := v.(type) {
case **uint64: case **uint64:
if data != nil { if data != nil && *data != nil {
field.ReflectValueOf(ctx, value).SetUint(**data) field.ReflectValueOf(ctx, value).SetUint(**data)
} }
case uint64: case uint64:
@ -718,7 +726,7 @@ func (field *Field) setupValuerAndSetter() {
field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) { field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
switch data := v.(type) { switch data := v.(type) {
case **float64: case **float64:
if data != nil { if data != nil && *data != nil {
field.ReflectValueOf(ctx, value).SetFloat(**data) field.ReflectValueOf(ctx, value).SetFloat(**data)
} }
case float64: case float64:
@ -761,10 +769,8 @@ func (field *Field) setupValuerAndSetter() {
case reflect.String: case reflect.String:
field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) { field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
switch data := v.(type) { switch data := v.(type) {
case *string:
field.ReflectValueOf(ctx, value).SetString(*data)
case **string: case **string:
if data != nil { if data != nil && *data != nil {
field.ReflectValueOf(ctx, value).SetString(**data) field.ReflectValueOf(ctx, value).SetString(**data)
} }
case string: case string:
@ -786,6 +792,10 @@ func (field *Field) setupValuerAndSetter() {
case time.Time: case time.Time:
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:
if data != nil && *data != nil {
field.Set(ctx, value, *data)
}
case time.Time: case time.Time:
field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(v)) field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(v))
case *time.Time: case *time.Time:
@ -808,6 +818,10 @@ func (field *Field) setupValuerAndSetter() {
case *time.Time: case *time.Time:
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:
if data != nil {
field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(*data))
}
case time.Time: case time.Time:
fieldValue := field.ReflectValueOf(ctx, value) fieldValue := field.ReflectValueOf(ctx, value)
if fieldValue.IsNil() { if fieldValue.IsNil() {