mirror of https://github.com/jackc/pgx.git
Extract plan wrapper concept
parent
a6863a7dd2
commit
67720623f8
|
@ -730,11 +730,15 @@ func (scanPlanString) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byt
|
||||||
return newPlan.Scan(ci, oid, formatCode, src, dst)
|
return newPlan.Scan(ci, oid, formatCode, src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type tryWrapScanPlanFunc func(dst interface{}) (plan WrappedScanPlanNextSetter, nextDst interface{}, ok bool)
|
||||||
|
|
||||||
type pointerPointerScanPlan struct {
|
type pointerPointerScanPlan struct {
|
||||||
dstType reflect.Type
|
dstType reflect.Type
|
||||||
next ScanPlan
|
next ScanPlan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (plan *pointerPointerScanPlan) SetNext(next ScanPlan) { plan.next = next }
|
||||||
|
|
||||||
func (plan *pointerPointerScanPlan) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
|
func (plan *pointerPointerScanPlan) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
|
||||||
if plan.dstType != reflect.TypeOf(dst) {
|
if plan.dstType != reflect.TypeOf(dst) {
|
||||||
newPlan := ci.PlanScan(oid, formatCode, dst)
|
newPlan := ci.PlanScan(oid, formatCode, dst)
|
||||||
|
@ -751,7 +755,7 @@ func (plan *pointerPointerScanPlan) Scan(ci *ConnInfo, oid uint32, formatCode in
|
||||||
return plan.next.Scan(ci, oid, formatCode, src, el.Interface())
|
return plan.next.Scan(ci, oid, formatCode, src, el.Interface())
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryPointerPointerScanPlan(dst interface{}) (plan *pointerPointerScanPlan, nextDst interface{}, ok bool) {
|
func tryPointerPointerScanPlan(dst interface{}) (plan WrappedScanPlanNextSetter, nextDst interface{}, ok bool) {
|
||||||
if dstValue := reflect.ValueOf(dst); dstValue.Kind() == reflect.Ptr {
|
if dstValue := reflect.ValueOf(dst); dstValue.Kind() == reflect.Ptr {
|
||||||
elemValue := dstValue.Elem()
|
elemValue := dstValue.Elem()
|
||||||
if elemValue.Kind() == reflect.Ptr {
|
if elemValue.Kind() == reflect.Ptr {
|
||||||
|
@ -790,6 +794,8 @@ type underlyingTypeScanPlan struct {
|
||||||
next ScanPlan
|
next ScanPlan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (plan *underlyingTypeScanPlan) SetNext(next ScanPlan) { plan.next = next }
|
||||||
|
|
||||||
func (plan *underlyingTypeScanPlan) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
|
func (plan *underlyingTypeScanPlan) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
|
||||||
if plan.dstType != reflect.TypeOf(dst) {
|
if plan.dstType != reflect.TypeOf(dst) {
|
||||||
newPlan := ci.PlanScan(oid, formatCode, dst)
|
newPlan := ci.PlanScan(oid, formatCode, dst)
|
||||||
|
@ -799,7 +805,7 @@ func (plan *underlyingTypeScanPlan) Scan(ci *ConnInfo, oid uint32, formatCode in
|
||||||
return plan.next.Scan(ci, oid, formatCode, src, reflect.ValueOf(dst).Convert(plan.nextDstType).Interface())
|
return plan.next.Scan(ci, oid, formatCode, src, reflect.ValueOf(dst).Convert(plan.nextDstType).Interface())
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryUnderlyingTypeScanPlan(dst interface{}) (plan *underlyingTypeScanPlan, nextDst interface{}, ok bool) {
|
func tryUnderlyingTypeScanPlan(dst interface{}) (plan WrappedScanPlanNextSetter, nextDst interface{}, ok bool) {
|
||||||
if _, ok := dst.(SkipUnderlyingTypePlanner); ok {
|
if _, ok := dst.(SkipUnderlyingTypePlanner); ok {
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
}
|
}
|
||||||
|
@ -1128,26 +1134,20 @@ func (ci *ConnInfo) PlanScan(oid uint32, formatCode int16, dst interface{}) Scan
|
||||||
return plan
|
return plan
|
||||||
}
|
}
|
||||||
|
|
||||||
if pointerPointerPlan, nextDst, ok := tryPointerPointerScanPlan(dst); ok {
|
tryWrappers := []tryWrapScanPlanFunc{
|
||||||
if nextPlan := ci.PlanScan(oid, formatCode, nextDst); nextPlan != nil {
|
tryPointerPointerScanPlan,
|
||||||
pointerPointerPlan.next = nextPlan
|
tryUnderlyingTypeScanPlan,
|
||||||
return pointerPointerPlan
|
tryWrapBuiltinTypeScanPlan,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if baseTypePlan, nextDst, ok := tryUnderlyingTypeScanPlan(dst); ok {
|
for _, f := range tryWrappers {
|
||||||
|
if wrapperPlan, nextDst, ok := f(dst); ok {
|
||||||
if nextPlan := ci.PlanScan(oid, formatCode, nextDst); nextPlan != nil {
|
if nextPlan := ci.PlanScan(oid, formatCode, nextDst); nextPlan != nil {
|
||||||
baseTypePlan.next = nextPlan
|
|
||||||
return baseTypePlan
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if wrapperPlan, nextValue, ok := tryWrapBuiltinTypeScanPlan(dst); ok {
|
|
||||||
if nextPlan := ci.PlanScan(oid, formatCode, nextValue); nextPlan != nil {
|
|
||||||
wrapperPlan.SetNext(nextPlan)
|
wrapperPlan.SetNext(nextPlan)
|
||||||
return wrapperPlan
|
return wrapperPlan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if _, ok := dst.(*interface{}); ok {
|
if _, ok := dst.(*interface{}); ok {
|
||||||
return &pointerEmptyInterfaceScanPlan{codec: dt.Codec}
|
return &pointerEmptyInterfaceScanPlan{codec: dt.Codec}
|
||||||
|
@ -1259,36 +1259,33 @@ func (ci *ConnInfo) PlanEncode(oid uint32, format int16, value interface{}) Enco
|
||||||
return plan
|
return plan
|
||||||
}
|
}
|
||||||
|
|
||||||
if derefPointerPlan, nextValue, ok := tryDerefPointerEncodePlan(value); ok {
|
tryWrappers := []tryWrapEncodePlanFunc{
|
||||||
if nextPlan := ci.PlanEncode(oid, format, nextValue); nextPlan != nil {
|
tryDerefPointerEncodePlan,
|
||||||
derefPointerPlan.next = nextPlan
|
tryUnderlyingTypeEncodePlan,
|
||||||
return derefPointerPlan
|
tryWrapBuiltinTypeEncodePlan,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if baseTypePlan, nextValue, ok := tryUnderlyingTypeEncodePlan(value); ok {
|
for _, f := range tryWrappers {
|
||||||
if nextPlan := ci.PlanEncode(oid, format, nextValue); nextPlan != nil {
|
if wrapperPlan, nextValue, ok := f(value); ok {
|
||||||
baseTypePlan.next = nextPlan
|
|
||||||
return baseTypePlan
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if wrapperPlan, nextValue, ok := tryWrapBuiltinTypeEncodePlan(value); ok {
|
|
||||||
if nextPlan := ci.PlanEncode(oid, format, nextValue); nextPlan != nil {
|
if nextPlan := ci.PlanEncode(oid, format, nextValue); nextPlan != nil {
|
||||||
wrapperPlan.SetNext(nextPlan)
|
wrapperPlan.SetNext(nextPlan)
|
||||||
return wrapperPlan
|
return wrapperPlan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type tryWrapEncodePlanFunc func(value interface{}) (plan WrappedEncodePlanNextSetter, nextValue interface{}, ok bool)
|
||||||
|
|
||||||
type derefPointerEncodePlan struct {
|
type derefPointerEncodePlan struct {
|
||||||
next EncodePlan
|
next EncodePlan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (plan *derefPointerEncodePlan) SetNext(next EncodePlan) { plan.next = next }
|
||||||
|
|
||||||
func (plan *derefPointerEncodePlan) Encode(value interface{}, buf []byte) (newBuf []byte, err error) {
|
func (plan *derefPointerEncodePlan) Encode(value interface{}, buf []byte) (newBuf []byte, err error) {
|
||||||
ptr := reflect.ValueOf(value)
|
ptr := reflect.ValueOf(value)
|
||||||
|
|
||||||
|
@ -1299,7 +1296,7 @@ func (plan *derefPointerEncodePlan) Encode(value interface{}, buf []byte) (newBu
|
||||||
return plan.next.Encode(ptr.Elem().Interface(), buf)
|
return plan.next.Encode(ptr.Elem().Interface(), buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryDerefPointerEncodePlan(value interface{}) (plan *derefPointerEncodePlan, nextValue interface{}, ok bool) {
|
func tryDerefPointerEncodePlan(value interface{}) (plan WrappedEncodePlanNextSetter, nextValue interface{}, ok bool) {
|
||||||
if valueType := reflect.TypeOf(value); valueType.Kind() == reflect.Ptr {
|
if valueType := reflect.TypeOf(value); valueType.Kind() == reflect.Ptr {
|
||||||
return &derefPointerEncodePlan{}, reflect.New(valueType.Elem()).Elem().Interface(), true
|
return &derefPointerEncodePlan{}, reflect.New(valueType.Elem()).Elem().Interface(), true
|
||||||
}
|
}
|
||||||
|
@ -1328,11 +1325,13 @@ type underlyingTypeEncodePlan struct {
|
||||||
next EncodePlan
|
next EncodePlan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (plan *underlyingTypeEncodePlan) SetNext(next EncodePlan) { plan.next = next }
|
||||||
|
|
||||||
func (plan *underlyingTypeEncodePlan) Encode(value interface{}, buf []byte) (newBuf []byte, err error) {
|
func (plan *underlyingTypeEncodePlan) Encode(value interface{}, buf []byte) (newBuf []byte, err error) {
|
||||||
return plan.next.Encode(reflect.ValueOf(value).Convert(plan.nextValueType).Interface(), buf)
|
return plan.next.Encode(reflect.ValueOf(value).Convert(plan.nextValueType).Interface(), buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryUnderlyingTypeEncodePlan(value interface{}) (plan *underlyingTypeEncodePlan, nextValue interface{}, ok bool) {
|
func tryUnderlyingTypeEncodePlan(value interface{}) (plan WrappedEncodePlanNextSetter, nextValue interface{}, ok bool) {
|
||||||
if _, ok := value.(SkipUnderlyingTypePlanner); ok {
|
if _, ok := value.(SkipUnderlyingTypePlanner); ok {
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue