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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		field.ReleaseScanValue = func(interface{}) {
 | 
							if field.NewValuePool == nil {
 | 
				
			||||||
 | 
								field.NewValuePool = fieldNewValuePool{
 | 
				
			||||||
 | 
									getter: func() interface{} {
 | 
				
			||||||
 | 
										return reflect.New(reflect.PtrTo(field.IndirectFieldType)).Interface()
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									putter: 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