mirror of https://github.com/VinGarcia/ksql.git
Refactor the structInfo struct so it can accept more information
parent
933ded26f4
commit
f5b7ab8028
|
@ -228,3 +228,7 @@ ok github.com/vingarcia/kissorm 21.740s
|
|||
- Implement support for nested objects with prefixed table names
|
||||
- Improve error messages
|
||||
- Add tests for tables using composite keys
|
||||
|
||||
### Optimizations Oportunities
|
||||
|
||||
- Test if using a pointer on the field info is faster or not
|
||||
|
|
13
kiss_orm.go
13
kiss_orm.go
|
@ -381,7 +381,7 @@ func (c DB) insertWithReturningID(
|
|||
for _, id := range idNames {
|
||||
scanFields = append(
|
||||
scanFields,
|
||||
v.Elem().Field(info.Index[id]).Addr().Interface(),
|
||||
v.Elem().Field(info.ByName(id).Index).Addr().Interface(),
|
||||
)
|
||||
}
|
||||
err = rows.Scan(scanFields...)
|
||||
|
@ -420,7 +420,7 @@ func (c DB) insertWithLastInsertID(
|
|||
vID := reflect.ValueOf(id)
|
||||
tID := vID.Type()
|
||||
|
||||
fieldAddr := v.Elem().Field(info.Index[idName]).Addr()
|
||||
fieldAddr := v.Elem().Field(info.ByName(idName).Index).Addr()
|
||||
fieldType := fieldAddr.Type().Elem()
|
||||
|
||||
if !tID.ConvertibleTo(fieldType) {
|
||||
|
@ -753,10 +753,11 @@ func scanRows(rows *sql.Rows, record interface{}) error {
|
|||
|
||||
scanArgs := []interface{}{}
|
||||
for _, name := range names {
|
||||
idx, found := info.Index[name]
|
||||
valueScanner := v.Field(idx).Addr()
|
||||
if !found {
|
||||
valueScanner = nopScannerValue
|
||||
fieldInfo := info.ByName(name)
|
||||
|
||||
valueScanner := nopScannerValue
|
||||
if fieldInfo.Valid {
|
||||
valueScanner = v.Field(fieldInfo.Index).Addr()
|
||||
}
|
||||
|
||||
scanArgs = append(scanArgs, valueScanner.Interface())
|
||||
|
|
|
@ -8,8 +8,36 @@ import (
|
|||
)
|
||||
|
||||
type structInfo struct {
|
||||
Names map[int]string
|
||||
Index map[string]int
|
||||
byIndex map[int]*fieldInfo
|
||||
byName map[string]*fieldInfo
|
||||
}
|
||||
|
||||
type fieldInfo struct {
|
||||
Name string
|
||||
Index int
|
||||
Valid bool
|
||||
}
|
||||
|
||||
func (s structInfo) ByIndex(idx int) *fieldInfo {
|
||||
field, found := s.byIndex[idx]
|
||||
if !found {
|
||||
return &fieldInfo{}
|
||||
}
|
||||
return field
|
||||
}
|
||||
|
||||
func (s structInfo) ByName(name string) *fieldInfo {
|
||||
field, found := s.byName[name]
|
||||
if !found {
|
||||
return &fieldInfo{}
|
||||
}
|
||||
return field
|
||||
}
|
||||
|
||||
func (s structInfo) Add(field fieldInfo) {
|
||||
field.Valid = true
|
||||
s.byIndex[field.Index] = &field
|
||||
s.byName[field.Name] = &field
|
||||
}
|
||||
|
||||
// This cache is kept as a pkg variable
|
||||
|
@ -72,7 +100,7 @@ func StructToMap(obj interface{}) (map[string]interface{}, error) {
|
|||
field = field.Elem()
|
||||
}
|
||||
|
||||
m[info.Names[i]] = field.Interface()
|
||||
m[info.ByIndex(i).Name] = field.Interface()
|
||||
}
|
||||
|
||||
return m, nil
|
||||
|
@ -107,15 +135,15 @@ func FillStructWith(record interface{}, dbRow map[string]interface{}) error {
|
|||
|
||||
info := getCachedTagInfo(tagInfoCache, t)
|
||||
for colName, rawSrc := range dbRow {
|
||||
fieldIdx, found := info.Index[colName]
|
||||
if !found {
|
||||
// Ignore columns not tagged with `kissorm:""`
|
||||
fieldInfo := info.ByName(colName)
|
||||
if !fieldInfo.Valid {
|
||||
// Ignore columns not tagged with `kissorm:"..."`
|
||||
continue
|
||||
}
|
||||
|
||||
src := NewPtrConverter(rawSrc)
|
||||
dest := v.Field(fieldIdx)
|
||||
destType := t.Field(info.Index[colName]).Type
|
||||
dest := v.Field(fieldInfo.Index)
|
||||
destType := t.Field(fieldInfo.Index).Type
|
||||
|
||||
destValue, err := src.Convert(destType)
|
||||
if err != nil {
|
||||
|
@ -259,16 +287,19 @@ func FillSliceWith(entities interface{}, dbRows []map[string]interface{}) error
|
|||
// which improves performance by a lot.
|
||||
func getTagNames(t reflect.Type) structInfo {
|
||||
info := structInfo{
|
||||
Names: map[int]string{},
|
||||
Index: map[string]int{},
|
||||
byIndex: map[int]*fieldInfo{},
|
||||
byName: map[string]*fieldInfo{},
|
||||
}
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
name := t.Field(i).Tag.Get("kissorm")
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
info.Names[i] = name
|
||||
info.Index[name] = i
|
||||
|
||||
info.Add(fieldInfo{
|
||||
Name: name,
|
||||
Index: i,
|
||||
})
|
||||
}
|
||||
|
||||
return info
|
||||
|
|
Loading…
Reference in New Issue