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 {
 | 
			
		||||
			values[idx] = reflectValue.Interface()
 | 
			
		||||
		} else if field := sch.LookUpField(column); field != nil && field.Readable {
 | 
			
		||||
			values[idx] = field.NewScanValue()
 | 
			
		||||
			defer field.ReleaseScanValue(values[idx])
 | 
			
		||||
			fieldValue := field.NewValuePool.Get()
 | 
			
		||||
			values[idx] = &fieldValue
 | 
			
		||||
			defer field.NewValuePool.Put(fieldValue)
 | 
			
		||||
		} else if names := strings.Split(column, "__"); len(names) > 1 {
 | 
			
		||||
			if rel, ok := sch.Relationships.Relations[names[0]]; ok {
 | 
			
		||||
				if field := rel.FieldSchema.LookUpField(strings.Join(names[1:], "__")); field != nil && field.Readable {
 | 
			
		||||
					values[idx] = field.NewScanValue()
 | 
			
		||||
					defer field.ReleaseScanValue(values[idx])
 | 
			
		||||
					fieldValue := field.NewValuePool.Get()
 | 
			
		||||
					values[idx] = &fieldValue
 | 
			
		||||
					defer field.NewValuePool.Put(fieldValue)
 | 
			
		||||
					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 field := rel.FieldSchema.LookUpField(strings.Join(names[1:], "__")); field != nil && field.Readable {
 | 
			
		||||
						relValue := rel.Field.ReflectValueOf(db.Statement.Context, reflectValue)
 | 
			
		||||
						value := reflect.ValueOf(values[idx]).Elem()
 | 
			
		||||
 | 
			
		||||
						if relValue.Kind() == reflect.Ptr && relValue.IsNil() {
 | 
			
		||||
							if value.IsNil() {
 | 
			
		||||
							if value := reflect.ValueOf(values[idx]).Elem(); value.Kind() == reflect.Ptr && value.IsNil() {
 | 
			
		||||
								continue
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							relValue.Set(reflect.New(relValue.Type().Elem()))
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -84,8 +84,7 @@ type Field struct {
 | 
			
		||||
	ReflectValueOf         func(context.Context, reflect.Value) reflect.Value
 | 
			
		||||
	ValueOf                func(context.Context, reflect.Value) (value interface{}, zero bool)
 | 
			
		||||
	Set                    func(context.Context, reflect.Value, interface{}) error
 | 
			
		||||
	NewScanValue           func() interface{}
 | 
			
		||||
	ReleaseScanValue       func(interface{})
 | 
			
		||||
	NewValuePool           FieldNewValuePool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseField parses reflect.StructField to Field
 | 
			
		||||
@ -415,31 +414,68 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	bytesPool = sync.Pool{
 | 
			
		||||
	stringPool = &sync.Pool{
 | 
			
		||||
		New: func() interface{} {
 | 
			
		||||
			bs := make([]byte, 0, 10)
 | 
			
		||||
			return &bs
 | 
			
		||||
			var v string
 | 
			
		||||
			return &v
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	bytesPoolReleaser = func(v interface{}) {
 | 
			
		||||
		bs := v.(*[]byte)
 | 
			
		||||
		*bs = (*bs)[:0]
 | 
			
		||||
		bytesPool.Put(bs)
 | 
			
		||||
	intPool = &sync.Pool{
 | 
			
		||||
		New: func() interface{} {
 | 
			
		||||
			var v int64
 | 
			
		||||
			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
 | 
			
		||||
func (field *Field) setupValuerAndSetter() {
 | 
			
		||||
	// Setup NewScanValue
 | 
			
		||||
	// Setup NewValuePool
 | 
			
		||||
	switch field.IndirectFieldType.Kind() {
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		field.NewScanValue = bytesPool.Get
 | 
			
		||||
		field.ReleaseScanValue = bytesPoolReleaser
 | 
			
		||||
		field.NewValuePool = stringPool
 | 
			
		||||
	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:
 | 
			
		||||
		field.NewScanValue = func() interface{} {
 | 
			
		||||
			return reflect.New(reflect.PtrTo(field.IndirectFieldType)).Interface()
 | 
			
		||||
		if field.IndirectFieldType == TimeReflectType {
 | 
			
		||||
			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) {
 | 
			
		||||
			case bool:
 | 
			
		||||
				field.ReflectValueOf(ctx, value).SetBool(data)
 | 
			
		||||
			case *bool:
 | 
			
		||||
			case **bool:
 | 
			
		||||
				if data != nil {
 | 
			
		||||
					field.ReflectValueOf(ctx, value).SetBool(*data)
 | 
			
		||||
					field.ReflectValueOf(ctx, value).SetBool(**data)
 | 
			
		||||
				} else {
 | 
			
		||||
					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:
 | 
			
		||||
		field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
			
		||||
			switch data := v.(type) {
 | 
			
		||||
			case **int64:
 | 
			
		||||
				if data != nil {
 | 
			
		||||
					field.ReflectValueOf(ctx, value).SetInt(**data)
 | 
			
		||||
				}
 | 
			
		||||
			case int64:
 | 
			
		||||
				field.ReflectValueOf(ctx, value).SetInt(data)
 | 
			
		||||
			case int:
 | 
			
		||||
@ -625,6 +665,10 @@ func (field *Field) setupValuerAndSetter() {
 | 
			
		||||
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
			
		||||
		field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
			
		||||
			switch data := v.(type) {
 | 
			
		||||
			case **uint64:
 | 
			
		||||
				if data != nil {
 | 
			
		||||
					field.ReflectValueOf(ctx, value).SetUint(**data)
 | 
			
		||||
				}
 | 
			
		||||
			case uint64:
 | 
			
		||||
				field.ReflectValueOf(ctx, value).SetUint(data)
 | 
			
		||||
			case uint:
 | 
			
		||||
@ -673,6 +717,10 @@ func (field *Field) setupValuerAndSetter() {
 | 
			
		||||
	case reflect.Float32, reflect.Float64:
 | 
			
		||||
		field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
			
		||||
			switch data := v.(type) {
 | 
			
		||||
			case **float64:
 | 
			
		||||
				if data != nil {
 | 
			
		||||
					field.ReflectValueOf(ctx, value).SetFloat(**data)
 | 
			
		||||
				}
 | 
			
		||||
			case float64:
 | 
			
		||||
				field.ReflectValueOf(ctx, value).SetFloat(data)
 | 
			
		||||
			case float32:
 | 
			
		||||
@ -713,6 +761,12 @@ func (field *Field) setupValuerAndSetter() {
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
 | 
			
		||||
			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:
 | 
			
		||||
				field.ReflectValueOf(ctx, value).SetString(data)
 | 
			
		||||
			case []byte:
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,25 @@ type GormDataTypeInterface interface {
 | 
			
		||||
	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
 | 
			
		||||
type Serializer struct {
 | 
			
		||||
	Field       *Field
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ require (
 | 
			
		||||
	github.com/jinzhu/now v1.1.4
 | 
			
		||||
	github.com/lib/pq v1.10.4
 | 
			
		||||
	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/postgres v1.2.3
 | 
			
		||||
	gorm.io/driver/sqlite v1.2.6
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user