Add pool manager
This commit is contained in:
parent
7e37f3ad75
commit
744c91c9a7
14
scan.go
14
scan.go
@ -55,13 +55,15 @@ 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 {
|
||||||
values[idx] = field.NewScanValue()
|
fieldValue := field.NewValuePool.Get()
|
||||||
defer field.ReleaseScanValue(values[idx])
|
values[idx] = &fieldValue
|
||||||
|
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 {
|
||||||
values[idx] = field.NewScanValue()
|
fieldValue := field.NewValuePool.Get()
|
||||||
defer field.ReleaseScanValue(values[idx])
|
values[idx] = &fieldValue
|
||||||
|
defer field.NewValuePool.Put(fieldValue)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,12 +87,12 @@ func (db *DB) scanIntoStruct(sch *schema.Schema, rows *sql.Rows, reflectValue re
|
|||||||
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 {
|
||||||
relValue := rel.Field.ReflectValueOf(db.Statement.Context, reflectValue)
|
relValue := rel.Field.ReflectValueOf(db.Statement.Context, reflectValue)
|
||||||
value := reflect.ValueOf(values[idx]).Elem()
|
|
||||||
|
|
||||||
if relValue.Kind() == reflect.Ptr && relValue.IsNil() {
|
if relValue.Kind() == reflect.Ptr && relValue.IsNil() {
|
||||||
if value.IsNil() {
|
if value := reflect.ValueOf(values[idx]).Elem(); value.Kind() == reflect.Ptr && value.IsNil() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
relValue.Set(reflect.New(relValue.Type().Elem()))
|
relValue.Set(reflect.New(relValue.Type().Elem()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,8 +84,7 @@ type Field struct {
|
|||||||
ReflectValueOf func(context.Context, reflect.Value) reflect.Value
|
ReflectValueOf func(context.Context, reflect.Value) reflect.Value
|
||||||
ValueOf func(context.Context, reflect.Value) (value interface{}, zero bool)
|
ValueOf func(context.Context, reflect.Value) (value interface{}, zero bool)
|
||||||
Set func(context.Context, reflect.Value, interface{}) error
|
Set func(context.Context, reflect.Value, interface{}) error
|
||||||
NewScanValue func() interface{}
|
NewValuePool FieldNewValuePool
|
||||||
ReleaseScanValue func(interface{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseField parses reflect.StructField to Field
|
// ParseField parses reflect.StructField to Field
|
||||||
@ -415,31 +414,68 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
bytesPool = sync.Pool{
|
stringPool = &sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() interface{} {
|
||||||
bs := make([]byte, 0, 10)
|
var v string
|
||||||
return &bs
|
return &v
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
bytesPoolReleaser = func(v interface{}) {
|
intPool = &sync.Pool{
|
||||||
bs := v.(*[]byte)
|
New: func() interface{} {
|
||||||
*bs = (*bs)[:0]
|
var v int64
|
||||||
bytesPool.Put(bs)
|
return &v
|
||||||
|
},
|
||||||
|
}
|
||||||
|
uintPool = &sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
var v uint64
|
||||||
|
return &v
|
||||||
|
},
|
||||||
|
}
|
||||||
|
floatPool = &sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
var v float64
|
||||||
|
return &v
|
||||||
|
},
|
||||||
|
}
|
||||||
|
boolPool = &sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
var v bool
|
||||||
|
return &v
|
||||||
|
},
|
||||||
|
}
|
||||||
|
timePool = &sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return &time.Time{}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// create valuer, setter when parse struct
|
// create valuer, setter when parse struct
|
||||||
func (field *Field) setupValuerAndSetter() {
|
func (field *Field) setupValuerAndSetter() {
|
||||||
// Setup NewScanValue
|
// Setup NewValuePool
|
||||||
switch field.IndirectFieldType.Kind() {
|
switch field.IndirectFieldType.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
field.NewScanValue = bytesPool.Get
|
field.NewValuePool = stringPool
|
||||||
field.ReleaseScanValue = bytesPoolReleaser
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
field.NewValuePool = intPool
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
field.NewValuePool = uintPool
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
field.NewValuePool = floatPool
|
||||||
|
case reflect.Bool:
|
||||||
|
field.NewValuePool = boolPool
|
||||||
default:
|
default:
|
||||||
field.NewScanValue = func() interface{} {
|
if field.IndirectFieldType == TimeReflectType {
|
||||||
return reflect.New(reflect.PtrTo(field.IndirectFieldType)).Interface()
|
field.NewValuePool = timePool
|
||||||
|
}
|
||||||
|
if field.NewValuePool == nil {
|
||||||
|
field.NewValuePool = fieldNewValuePool{
|
||||||
|
getter: func() interface{} {
|
||||||
|
return reflect.New(reflect.PtrTo(field.IndirectFieldType)).Interface()
|
||||||
|
},
|
||||||
|
putter: func(interface{}) {},
|
||||||
}
|
}
|
||||||
field.ReleaseScanValue = func(interface{}) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,9 +582,9 @@ func (field *Field) setupValuerAndSetter() {
|
|||||||
switch data := v.(type) {
|
switch data := v.(type) {
|
||||||
case bool:
|
case bool:
|
||||||
field.ReflectValueOf(ctx, value).SetBool(data)
|
field.ReflectValueOf(ctx, value).SetBool(data)
|
||||||
case *bool:
|
case **bool:
|
||||||
if data != nil {
|
if data != nil {
|
||||||
field.ReflectValueOf(ctx, value).SetBool(*data)
|
field.ReflectValueOf(ctx, value).SetBool(**data)
|
||||||
} else {
|
} else {
|
||||||
field.ReflectValueOf(ctx, value).SetBool(false)
|
field.ReflectValueOf(ctx, value).SetBool(false)
|
||||||
}
|
}
|
||||||
@ -565,6 +601,10 @@ func (field *Field) setupValuerAndSetter() {
|
|||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
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:
|
||||||
|
if data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetInt(**data)
|
||||||
|
}
|
||||||
case int64:
|
case int64:
|
||||||
field.ReflectValueOf(ctx, value).SetInt(data)
|
field.ReflectValueOf(ctx, value).SetInt(data)
|
||||||
case int:
|
case int:
|
||||||
@ -625,6 +665,10 @@ func (field *Field) setupValuerAndSetter() {
|
|||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
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:
|
||||||
|
if data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetUint(**data)
|
||||||
|
}
|
||||||
case uint64:
|
case uint64:
|
||||||
field.ReflectValueOf(ctx, value).SetUint(data)
|
field.ReflectValueOf(ctx, value).SetUint(data)
|
||||||
case uint:
|
case uint:
|
||||||
@ -673,6 +717,10 @@ func (field *Field) setupValuerAndSetter() {
|
|||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
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:
|
||||||
|
if data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetFloat(**data)
|
||||||
|
}
|
||||||
case float64:
|
case float64:
|
||||||
field.ReflectValueOf(ctx, value).SetFloat(data)
|
field.ReflectValueOf(ctx, value).SetFloat(data)
|
||||||
case float32:
|
case float32:
|
||||||
@ -713,6 +761,12 @@ 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:
|
||||||
|
if data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetString(**data)
|
||||||
|
}
|
||||||
case string:
|
case string:
|
||||||
field.ReflectValueOf(ctx, value).SetString(data)
|
field.ReflectValueOf(ctx, value).SetString(data)
|
||||||
case []byte:
|
case []byte:
|
||||||
|
@ -13,6 +13,25 @@ type GormDataTypeInterface interface {
|
|||||||
GormDataType() string
|
GormDataType() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FieldNewValuePool field new scan value pool
|
||||||
|
type FieldNewValuePool interface {
|
||||||
|
Get() interface{}
|
||||||
|
Put(interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type fieldNewValuePool struct {
|
||||||
|
getter func() interface{}
|
||||||
|
putter func(interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fp fieldNewValuePool) Get() interface{} {
|
||||||
|
return fp.getter()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fp fieldNewValuePool) Put(v interface{}) {
|
||||||
|
fp.putter(v)
|
||||||
|
}
|
||||||
|
|
||||||
// Serializer field value serializer
|
// Serializer field value serializer
|
||||||
type Serializer struct {
|
type Serializer struct {
|
||||||
Field *Field
|
Field *Field
|
||||||
|
@ -9,7 +9,7 @@ require (
|
|||||||
github.com/jinzhu/now v1.1.4
|
github.com/jinzhu/now v1.1.4
|
||||||
github.com/lib/pq v1.10.4
|
github.com/lib/pq v1.10.4
|
||||||
github.com/mattn/go-sqlite3 v1.14.11 // indirect
|
github.com/mattn/go-sqlite3 v1.14.11 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220213190939-1e6e3497d506 // indirect
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
|
||||||
gorm.io/driver/mysql v1.2.3
|
gorm.io/driver/mysql v1.2.3
|
||||||
gorm.io/driver/postgres v1.2.3
|
gorm.io/driver/postgres v1.2.3
|
||||||
gorm.io/driver/sqlite v1.2.6
|
gorm.io/driver/sqlite v1.2.6
|
||||||
|
Loading…
x
Reference in New Issue
Block a user