Finish Insert() caching.
This commit is contained in:
parent
793306d749
commit
acad9f7de5
7 changed files with 65 additions and 39 deletions
|
@ -237,12 +237,12 @@ func bind(rows *sql.Rows, obj interface{}, structType, sliceType reflect.Type, b
|
|||
|
||||
switch bkind {
|
||||
case kindStruct:
|
||||
pointers = ptrsFromMapping(reflect.Indirect(reflect.ValueOf(obj)), mapping)
|
||||
pointers = PtrsFromMapping(reflect.Indirect(reflect.ValueOf(obj)), mapping)
|
||||
case kindSliceStruct:
|
||||
pointers = ptrsFromMapping(oneStruct, mapping)
|
||||
pointers = PtrsFromMapping(oneStruct, mapping)
|
||||
case kindPtrSliceStruct:
|
||||
newStruct = reflect.New(structType)
|
||||
pointers = ptrsFromMapping(reflect.Indirect(newStruct), mapping)
|
||||
pointers = PtrsFromMapping(reflect.Indirect(newStruct), mapping)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -295,19 +295,29 @@ ColLoop:
|
|||
return ptrs, nil
|
||||
}
|
||||
|
||||
// ptrsFromMapping expects to be passed an addressable struct that it's looking
|
||||
// for things on.
|
||||
func ptrsFromMapping(val reflect.Value, mapping []uint64) []interface{} {
|
||||
// PtrsFromMapping expects to be passed an addressable struct and a mapping
|
||||
// of where to find things. It pulls the pointers out referred to by the mapping.
|
||||
func PtrsFromMapping(val reflect.Value, mapping []uint64) []interface{} {
|
||||
ptrs := make([]interface{}, len(mapping))
|
||||
for i, m := range mapping {
|
||||
ptrs[i] = ptrFromMapping(val, m).Interface()
|
||||
ptrs[i] = ptrFromMapping(val, m, true).Interface()
|
||||
}
|
||||
return ptrs
|
||||
}
|
||||
|
||||
// ValuesFromMapping expects to be passed an addressable struct and a mapping
|
||||
// of where to find things. It pulls the pointers out referred to by the mapping.
|
||||
func ValuesFromMapping(val reflect.Value, mapping []uint64) []interface{} {
|
||||
ptrs := make([]interface{}, len(mapping))
|
||||
for i, m := range mapping {
|
||||
ptrs[i] = ptrFromMapping(val, m, false).Interface()
|
||||
}
|
||||
return ptrs
|
||||
}
|
||||
|
||||
// ptrFromMapping expects to be passed an addressable struct that it's looking
|
||||
// for things on.
|
||||
func ptrFromMapping(val reflect.Value, mapping uint64) reflect.Value {
|
||||
func ptrFromMapping(val reflect.Value, mapping uint64, addressOf bool) reflect.Value {
|
||||
for i := 0; i < 8; i++ {
|
||||
v := (mapping >> uint(i*8)) & sentinel
|
||||
|
||||
|
|
|
@ -247,19 +247,19 @@ func TestPtrFromMapping(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
v := ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(0))
|
||||
v := ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(0), true)
|
||||
if got := *v.Interface().(*int); got != 5 {
|
||||
t.Error("flat int was wrong:", got)
|
||||
}
|
||||
v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(1))
|
||||
v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(1), true)
|
||||
if got := *v.Interface().(*int); got != 0 {
|
||||
t.Error("flat pointer was wrong:", got)
|
||||
}
|
||||
v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(2, 0))
|
||||
v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(2, 0), true)
|
||||
if got := *v.Interface().(*int); got != 6 {
|
||||
t.Error("nested int was wrong:", got)
|
||||
}
|
||||
v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(2, 1))
|
||||
v = ptrFromMapping(reflect.Indirect(reflect.ValueOf(val)), testMakeMapping(2, 1), true)
|
||||
if got := *v.Interface().(*int); got != 0 {
|
||||
t.Error("nested pointer was wrong:", got)
|
||||
}
|
||||
|
|
|
@ -146,6 +146,8 @@ var defaultTemplateImports = imports{
|
|||
`"fmt"`,
|
||||
`"strings"`,
|
||||
`"database/sql"`,
|
||||
`"reflect"`,
|
||||
`"sync"`,
|
||||
`"time"`,
|
||||
},
|
||||
thirdParty: importList{
|
||||
|
@ -166,6 +168,7 @@ var defaultSingletonTemplateImports = map[string]imports{
|
|||
"boil_types": {
|
||||
thirdParty: importList{
|
||||
`"github.com/pkg/errors"`,
|
||||
`"github.com/vattle/sqlboiler/strmangle"`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
{{if .Table.IsJoinTable -}}
|
||||
{{else -}}
|
||||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
{{- $tableNameSingular := .Table.Name | singular | titleCase -}}
|
||||
var (
|
||||
|
@ -20,26 +22,14 @@ type (
|
|||
|
||||
// Cache for insert and update
|
||||
var (
|
||||
{{$varNameSingular}}Mapping = boil.MakeStructMapping(&{{$tableNameSingular}}{})
|
||||
{{$varNameSingular}}InsertCacheMut sync.RMutex
|
||||
{{$varNameSingular}}Type = reflect.TypeOf(&{{$tableNameSingular}}{})
|
||||
{{$varNameSingular}}Mapping = boil.MakeStructMapping({{$varNameSingular}}Type)
|
||||
{{$varNameSingular}}InsertCacheMut sync.RWMutex
|
||||
{{$varNameSingular}}InsertCache = make(map[string]insertCache)
|
||||
{{$varNameSingular}}UpdateCacheMut sync.RMutex
|
||||
{{$varNameSingular}}UpdateCacheMut sync.RWMutex
|
||||
{{$varNameSingular}}UpdateCache = make(map[string]updateCache)
|
||||
)
|
||||
|
||||
func makeCacheKey(wl, nzDefaults []string) string {
|
||||
buf := strmangle.GetBuffer()
|
||||
|
||||
for _, w := range wl {
|
||||
buf.WriteString(w)
|
||||
}
|
||||
for _, nz := range nzDefaults {
|
||||
buf.WriteString(nz)
|
||||
}
|
||||
|
||||
str := buf.String()
|
||||
strmangle.PutBuffer(buf)
|
||||
}
|
||||
|
||||
// Force time package dependency for automated UpdatedAt/CreatedAt.
|
||||
var _ = time.Second
|
||||
{{end -}}
|
||||
|
|
|
@ -56,20 +56,26 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
|||
whitelist,
|
||||
)
|
||||
|
||||
typ := reflect.TypeOf(o)
|
||||
cache.valueMapping = boil.BindMapping(typ, {{$varNameSingular}}Mapping, wl)
|
||||
cache.retMapping = boil.BindMapping(typ, {{$varNameSingular}}Mapping, returnColumns)
|
||||
cache.valueMapping, err = boil.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, wl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cache.retMapping, err = boil.BindMapping({{$varNameSingular}}Type, {{$varNameSingular}}Mapping, returnColumns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cache.query = fmt.Sprintf(`INSERT INTO {{.Table.Name}} ("%s") VALUES (%s)`, strings.Join(wl, `","`), strmangle.Placeholders(len(wl), 1, 1))
|
||||
|
||||
if len(cache.retMapping) != 0 {
|
||||
{{if .UseLastInsertID -}}
|
||||
cache.query += fmt.Sprintf(` RETURNING %s`, strings.Join(returnColumns, ","))
|
||||
{{else -}}
|
||||
cache.retQuery = fmt.Sprintf(`SELECT %s FROM {{.Table.Name}} WHERE %s`, strings.Join(returnColumns, `","`), strmangle.WhereClause(1, {{$varNameSingular}}AutoIncPrimaryKeys))
|
||||
{{else -}}
|
||||
cache.query += fmt.Sprintf(` RETURNING %s`, strings.Join(returnColumns, ","))
|
||||
{{end -}}
|
||||
}
|
||||
}
|
||||
|
||||
value := reflect.Indirect(reflect.ValueOf(o))
|
||||
{{if .UseLastInsertID}}
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, ins)
|
||||
|
@ -99,15 +105,16 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
|||
return errors.Wrap(err, "{{.PkgName}}: unable to populate default values for {{.Table.Name}}")
|
||||
}
|
||||
{{else}}
|
||||
vals := boil.ValuesFromMapping(value, cache.valueMapping)
|
||||
if len(cache.retMapping) != 0 {
|
||||
err = exec.QueryRow(cache.query, boil.GetStructValues(o, wl...)...).Scan(boil.GetStructPointers(o, returnColumns...)...)
|
||||
err = exec.QueryRow(cache.query, vals...).Scan(boil.PtrsFromMapping(value, cache.retMapping)...)
|
||||
} else {
|
||||
_, err = exec.Exec(cache.query, boil.GetStructValues(o, wl...)...)
|
||||
_, err = exec.Exec(cache.query, vals...)
|
||||
}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, ins)
|
||||
fmt.Fprintln(boil.DebugWriter, boil.GetStructValues(o, wl...))
|
||||
fmt.Fprintln(boil.DebugWriter, cache.query)
|
||||
fmt.Fprintln(boil.DebugWriter, vals)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -40,7 +40,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, updateOnConflict boo
|
|||
{{$varNameSingular}}Columns,
|
||||
{{$varNameSingular}}ColumnsWithDefault,
|
||||
{{$varNameSingular}}ColumnsWithoutDefault,
|
||||
boil.NonZeroDefaultSet({{$varNameSingular}}ColumnsWithDefault, {{$varNameSingular}}TitleCases, o),
|
||||
boil.NonZeroDefaultSet({{$varNameSingular}}ColumnsWithDefault, o),
|
||||
whitelist,
|
||||
)
|
||||
update := strmangle.UpdateColumnSet(
|
||||
|
|
|
@ -17,3 +17,19 @@ type updateCache struct{
|
|||
query string
|
||||
valueMapping []uint64
|
||||
}
|
||||
|
||||
func makeCacheKey(wl, nzDefaults []string) string {
|
||||
buf := strmangle.GetBuffer()
|
||||
|
||||
for _, w := range wl {
|
||||
buf.WriteString(w)
|
||||
}
|
||||
for _, nz := range nzDefaults {
|
||||
buf.WriteString(nz)
|
||||
}
|
||||
|
||||
str := buf.String()
|
||||
strmangle.PutBuffer(buf)
|
||||
return str
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue