v0.0.369 autom. allow usage of existing converter for pointer-types (sq)
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m29s
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m29s
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/jmoiron/sqlx/reflectx"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// forked from sqlx, but added ability to unmarshal optional-nested structs
|
||||
@@ -18,7 +19,7 @@ type StructScanner struct {
|
||||
|
||||
fields [][]int
|
||||
values []any
|
||||
converter []DBTypeConverter
|
||||
converter []ssConverter
|
||||
columns []string
|
||||
}
|
||||
|
||||
@@ -30,6 +31,11 @@ func NewStructScanner(rows *sqlx.Rows, unsafe bool) *StructScanner {
|
||||
}
|
||||
}
|
||||
|
||||
type ssConverter struct {
|
||||
Converter DBTypeConverter
|
||||
RefCount int
|
||||
}
|
||||
|
||||
func (r *StructScanner) Start(dest any) error {
|
||||
v := reflect.ValueOf(dest)
|
||||
|
||||
@@ -49,7 +55,7 @@ func (r *StructScanner) Start(dest any) error {
|
||||
return fmt.Errorf("missing destination name %s in %T", columns[f], dest)
|
||||
}
|
||||
r.values = make([]interface{}, len(columns))
|
||||
r.converter = make([]DBTypeConverter, len(columns))
|
||||
r.converter = make([]ssConverter, len(columns))
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -143,13 +149,19 @@ func (r *StructScanner) StructScanExt(q Queryable, dest any) error {
|
||||
|
||||
f.Set(reflect.Zero(f.Type())) // set to nil
|
||||
} else {
|
||||
if r.converter[i] != nil {
|
||||
val3 := val2.Elem().Interface()
|
||||
conv3, err := r.converter[i].DBToModel(val3)
|
||||
if r.converter[i].Converter != nil {
|
||||
val3 := val2.Elem()
|
||||
conv3, err := r.converter[i].Converter.DBToModel(val3.Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.Set(reflect.ValueOf(conv3))
|
||||
conv3RVal := reflect.ValueOf(conv3)
|
||||
for j := 0; j < r.converter[i].RefCount; j++ {
|
||||
newConv3Val := reflect.New(conv3RVal.Type())
|
||||
newConv3Val.Elem().Set(conv3RVal)
|
||||
conv3RVal = newConv3Val
|
||||
}
|
||||
f.Set(conv3RVal)
|
||||
} else {
|
||||
f.Set(val2.Elem())
|
||||
}
|
||||
@@ -184,7 +196,7 @@ func (r *StructScanner) StructScanBase(dest any) error {
|
||||
}
|
||||
|
||||
// fieldsByTraversal forked from github.com/jmoiron/sqlx@v1.3.5/sqlx.go
|
||||
func fieldsByTraversalExtended(q Queryable, v reflect.Value, traversals [][]int, values []interface{}, converter []DBTypeConverter) error {
|
||||
func fieldsByTraversalExtended(q Queryable, v reflect.Value, traversals [][]int, values []interface{}, converter []ssConverter) error {
|
||||
v = reflect.Indirect(v)
|
||||
if v.Kind() != reflect.Struct {
|
||||
return errors.New("argument not a struct")
|
||||
@@ -205,14 +217,26 @@ func fieldsByTraversalExtended(q Queryable, v reflect.Value, traversals [][]int,
|
||||
_v := langext.Ptr[any](nil)
|
||||
values[i] = _v
|
||||
foundConverter = true
|
||||
converter[i] = conv
|
||||
converter[i] = ssConverter{Converter: conv, RefCount: 0}
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundConverter {
|
||||
// also allow non-pointer converter for pointer-types
|
||||
for _, conv := range q.ListConverter() {
|
||||
if conv.ModelTypeString() == strings.TrimLeft(typeStr, "*") {
|
||||
_v := langext.Ptr[any](nil)
|
||||
values[i] = _v
|
||||
foundConverter = true
|
||||
converter[i] = ssConverter{Converter: conv, RefCount: len(typeStr) - len(strings.TrimLeft(typeStr, "*"))} // kind hacky way to get the amount of ptr before <f>, but it works...
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !foundConverter {
|
||||
values[i] = reflect.New(reflect.PointerTo(f.Type())).Interface()
|
||||
converter[i] = nil
|
||||
converter[i] = ssConverter{Converter: nil, RefCount: -1}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
Reference in New Issue
Block a user