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
|
- Implement support for nested objects with prefixed table names
|
||||||
- Improve error messages
|
- Improve error messages
|
||||||
- Add tests for tables using composite keys
|
- 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 {
|
for _, id := range idNames {
|
||||||
scanFields = append(
|
scanFields = append(
|
||||||
scanFields,
|
scanFields,
|
||||||
v.Elem().Field(info.Index[id]).Addr().Interface(),
|
v.Elem().Field(info.ByName(id).Index).Addr().Interface(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
err = rows.Scan(scanFields...)
|
err = rows.Scan(scanFields...)
|
||||||
|
@ -420,7 +420,7 @@ func (c DB) insertWithLastInsertID(
|
||||||
vID := reflect.ValueOf(id)
|
vID := reflect.ValueOf(id)
|
||||||
tID := vID.Type()
|
tID := vID.Type()
|
||||||
|
|
||||||
fieldAddr := v.Elem().Field(info.Index[idName]).Addr()
|
fieldAddr := v.Elem().Field(info.ByName(idName).Index).Addr()
|
||||||
fieldType := fieldAddr.Type().Elem()
|
fieldType := fieldAddr.Type().Elem()
|
||||||
|
|
||||||
if !tID.ConvertibleTo(fieldType) {
|
if !tID.ConvertibleTo(fieldType) {
|
||||||
|
@ -753,10 +753,11 @@ func scanRows(rows *sql.Rows, record interface{}) error {
|
||||||
|
|
||||||
scanArgs := []interface{}{}
|
scanArgs := []interface{}{}
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
idx, found := info.Index[name]
|
fieldInfo := info.ByName(name)
|
||||||
valueScanner := v.Field(idx).Addr()
|
|
||||||
if !found {
|
valueScanner := nopScannerValue
|
||||||
valueScanner = nopScannerValue
|
if fieldInfo.Valid {
|
||||||
|
valueScanner = v.Field(fieldInfo.Index).Addr()
|
||||||
}
|
}
|
||||||
|
|
||||||
scanArgs = append(scanArgs, valueScanner.Interface())
|
scanArgs = append(scanArgs, valueScanner.Interface())
|
||||||
|
|
|
@ -8,8 +8,36 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type structInfo struct {
|
type structInfo struct {
|
||||||
Names map[int]string
|
byIndex map[int]*fieldInfo
|
||||||
Index map[string]int
|
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
|
// This cache is kept as a pkg variable
|
||||||
|
@ -72,7 +100,7 @@ func StructToMap(obj interface{}) (map[string]interface{}, error) {
|
||||||
field = field.Elem()
|
field = field.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
m[info.Names[i]] = field.Interface()
|
m[info.ByIndex(i).Name] = field.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
|
@ -107,15 +135,15 @@ func FillStructWith(record interface{}, dbRow map[string]interface{}) error {
|
||||||
|
|
||||||
info := getCachedTagInfo(tagInfoCache, t)
|
info := getCachedTagInfo(tagInfoCache, t)
|
||||||
for colName, rawSrc := range dbRow {
|
for colName, rawSrc := range dbRow {
|
||||||
fieldIdx, found := info.Index[colName]
|
fieldInfo := info.ByName(colName)
|
||||||
if !found {
|
if !fieldInfo.Valid {
|
||||||
// Ignore columns not tagged with `kissorm:""`
|
// Ignore columns not tagged with `kissorm:"..."`
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
src := NewPtrConverter(rawSrc)
|
src := NewPtrConverter(rawSrc)
|
||||||
dest := v.Field(fieldIdx)
|
dest := v.Field(fieldInfo.Index)
|
||||||
destType := t.Field(info.Index[colName]).Type
|
destType := t.Field(fieldInfo.Index).Type
|
||||||
|
|
||||||
destValue, err := src.Convert(destType)
|
destValue, err := src.Convert(destType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -259,16 +287,19 @@ func FillSliceWith(entities interface{}, dbRows []map[string]interface{}) error
|
||||||
// which improves performance by a lot.
|
// which improves performance by a lot.
|
||||||
func getTagNames(t reflect.Type) structInfo {
|
func getTagNames(t reflect.Type) structInfo {
|
||||||
info := structInfo{
|
info := structInfo{
|
||||||
Names: map[int]string{},
|
byIndex: map[int]*fieldInfo{},
|
||||||
Index: map[string]int{},
|
byName: map[string]*fieldInfo{},
|
||||||
}
|
}
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
name := t.Field(i).Tag.Get("kissorm")
|
name := t.Field(i).Tag.Get("kissorm")
|
||||||
if name == "" {
|
if name == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
info.Names[i] = name
|
|
||||||
info.Index[name] = i
|
info.Add(fieldInfo{
|
||||||
|
Name: name,
|
||||||
|
Index: i,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
Loading…
Reference in New Issue