Qrm refactor

- Allow custom types Scan method to read values returned by the driver rather then the value from intermediate Null types. Scan to intermidiate Null types removed.
- Better error handling
This commit is contained in:
go-jet 2021-10-15 17:43:10 +02:00
parent 555ec293fb
commit 0d418890ab
11 changed files with 459 additions and 574 deletions

View file

@ -2,10 +2,7 @@ package qrm
import (
"database/sql"
"database/sql/driver"
"fmt"
"github.com/go-jet/jet/v2/internal/utils"
"github.com/go-jet/jet/v2/internal/utils/throw"
"reflect"
"strings"
)
@ -46,7 +43,7 @@ func newScanContext(rows *sql.Rows) (*scanContext, error) {
}
return &scanContext{
row: createScanValue(columnTypes),
row: createScanSlice(len(columnTypes)),
uniqueDestObjectsMap: make(map[string]int),
groupKeyInfoCache: make(map[string]groupKeyInfo),
@ -56,6 +53,17 @@ func newScanContext(rows *sql.Rows) (*scanContext, error) {
}, nil
}
func createScanSlice(columnCount int) []interface{} {
scanSlice := make([]interface{}, columnCount)
scanPtrSlice := make([]interface{}, columnCount)
for i := range scanPtrSlice {
scanPtrSlice[i] = &scanSlice[i] // if destination is pointer to interface sql.Scan will just forward driver value
}
return scanPtrSlice
}
type typeInfo struct {
fieldMappings []fieldMapping
}
@ -210,16 +218,13 @@ func (s *scanContext) typeToColumnIndex(typeName, fieldName string) int {
}
func (s *scanContext) rowElem(index int) interface{} {
cellValue := reflect.ValueOf(s.row[index])
valuer, ok := s.row[index].(driver.Valuer)
if cellValue.IsValid() && !cellValue.IsNil() {
return cellValue.Elem().Interface()
}
utils.MustBeTrue(ok, "jet: internal error, scan value doesn't implement driver.Valuer")
value, err := valuer.Value()
throw.OnError(err)
return value
return nil
}
func (s *scanContext) rowElemValuePtr(index int) reflect.Value {