Add TitleCase cache
This commit is contained in:
parent
b101df0a24
commit
09fb8005f6
13 changed files with 69 additions and 103 deletions
|
@ -20,7 +20,7 @@ same SQL helpers and wrappers for every project we were creating, but did not wa
|
|||
there that utilize the "code-first" approach. `SQLX` is a great project, but very minimalistic and still requires a
|
||||
considerable amount of boilerplate for every project. Originally this project started as a SQL boilerplate generator (hence the name)
|
||||
that generated simple helper functions, but we found that we could accomplish the same task by turning it into a
|
||||
(mostly) fully fledged ORM, without any sacrifice in performance or congruency, but generous gains in flexibility.
|
||||
(mostly) fully fledged ORM generator, without any sacrifice in performance or congruency, but generous gains in flexibility.
|
||||
|
||||
The approach we've taken has afforded us the following benefits:
|
||||
|
||||
|
|
|
@ -74,18 +74,12 @@ func (q *Query) BindP(obj interface{}) {
|
|||
// For custom objects that want to use eager loading, please see the
|
||||
// loadRelationships function.
|
||||
func Bind(rows *sql.Rows, obj interface{}) error {
|
||||
return BindFast(rows, obj, nil)
|
||||
}
|
||||
|
||||
// BindFast uses a lookup table for column_name to ColumnName to avoid TitleCase.
|
||||
func BindFast(rows *sql.Rows, obj interface{}, titleCases map[string]string) error {
|
||||
structType, sliceType, singular, err := bindChecks(obj)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bind(rows, obj, structType, sliceType, singular, titleCases)
|
||||
return bind(rows, obj, structType, sliceType, singular)
|
||||
}
|
||||
|
||||
// Bind executes the query and inserts the
|
||||
|
@ -93,11 +87,6 @@ func BindFast(rows *sql.Rows, obj interface{}, titleCases map[string]string) err
|
|||
//
|
||||
// See documentation for boil.Bind()
|
||||
func (q *Query) Bind(obj interface{}) error {
|
||||
return q.BindFast(obj, nil)
|
||||
}
|
||||
|
||||
// BindFast uses a lookup table for column_name to ColumnName to avoid TitleCase.
|
||||
func (q *Query) BindFast(obj interface{}, titleCases map[string]string) error {
|
||||
structType, sliceType, singular, err := bindChecks(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -108,8 +97,7 @@ func (q *Query) BindFast(obj interface{}, titleCases map[string]string) error {
|
|||
return errors.Wrap(err, "bind failed to execute query")
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if res := bind(rows, obj, structType, sliceType, singular, titleCases); res != nil {
|
||||
if res := bind(rows, obj, structType, sliceType, singular); res != nil {
|
||||
return res
|
||||
}
|
||||
|
||||
|
@ -255,7 +243,7 @@ func bindChecks(obj interface{}) (structType reflect.Type, sliceType reflect.Typ
|
|||
return structType, sliceType, singular, nil
|
||||
}
|
||||
|
||||
func bind(rows *sql.Rows, obj interface{}, structType, sliceType reflect.Type, singular bool, titleCases map[string]string) error {
|
||||
func bind(rows *sql.Rows, obj interface{}, structType, sliceType reflect.Type, singular bool) error {
|
||||
cols, err := rows.Columns()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "bind failed to get column names")
|
||||
|
@ -275,7 +263,7 @@ func bind(rows *sql.Rows, obj interface{}, structType, sliceType reflect.Type, s
|
|||
mut.RUnlock()
|
||||
|
||||
if !ok {
|
||||
mapping, err = bindMapping(structType, titleCases, cols)
|
||||
mapping, err = bindMapping(structType, cols)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -317,13 +305,13 @@ func bind(rows *sql.Rows, obj interface{}, structType, sliceType reflect.Type, s
|
|||
return nil
|
||||
}
|
||||
|
||||
func bindMapping(typ reflect.Type, titleCases map[string]string, cols []string) ([]uint64, error) {
|
||||
func bindMapping(typ reflect.Type, cols []string) ([]uint64, error) {
|
||||
ptrs := make([]uint64, len(cols))
|
||||
mapping := makeStructMapping(typ, titleCases)
|
||||
mapping := makeStructMapping(typ)
|
||||
|
||||
ColLoop:
|
||||
for i, c := range cols {
|
||||
name := strmangle.TitleCaseIdentifier(c, titleCases)
|
||||
name := strmangle.TitleCaseIdentifier(c)
|
||||
ptrMap, ok := mapping[name]
|
||||
if ok {
|
||||
ptrs[i] = ptrMap
|
||||
|
@ -376,13 +364,13 @@ func ptrFromMapping(val reflect.Value, mapping uint64) reflect.Value {
|
|||
panic("could not find pointer from mapping")
|
||||
}
|
||||
|
||||
func makeStructMapping(typ reflect.Type, titleCases map[string]string) map[string]uint64 {
|
||||
func makeStructMapping(typ reflect.Type) map[string]uint64 {
|
||||
fieldMaps := make(map[string]uint64)
|
||||
makeStructMappingHelper(typ, "", 0, 0, fieldMaps, titleCases)
|
||||
makeStructMappingHelper(typ, "", 0, 0, fieldMaps)
|
||||
return fieldMaps
|
||||
}
|
||||
|
||||
func makeStructMappingHelper(typ reflect.Type, prefix string, current uint64, depth uint, fieldMaps map[string]uint64, titleCases map[string]string) {
|
||||
func makeStructMappingHelper(typ reflect.Type, prefix string, current uint64, depth uint, fieldMaps map[string]uint64) {
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
|
@ -391,7 +379,7 @@ func makeStructMappingHelper(typ reflect.Type, prefix string, current uint64, de
|
|||
for i := 0; i < n; i++ {
|
||||
f := typ.Field(i)
|
||||
|
||||
tag, recurse := getBoilTag(f, titleCases)
|
||||
tag, recurse := getBoilTag(f)
|
||||
if len(tag) == 0 {
|
||||
tag = f.Name
|
||||
} else if tag[0] == '-' {
|
||||
|
@ -403,7 +391,7 @@ func makeStructMappingHelper(typ reflect.Type, prefix string, current uint64, de
|
|||
}
|
||||
|
||||
if recurse {
|
||||
makeStructMappingHelper(f.Type, tag, current|uint64(i)<<depth, depth+8, fieldMaps, titleCases)
|
||||
makeStructMappingHelper(f.Type, tag, current|uint64(i)<<depth, depth+8, fieldMaps)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -411,7 +399,7 @@ func makeStructMappingHelper(typ reflect.Type, prefix string, current uint64, de
|
|||
}
|
||||
}
|
||||
|
||||
func getBoilTag(field reflect.StructField, titleCases map[string]string) (name string, recurse bool) {
|
||||
func getBoilTag(field reflect.StructField) (name string, recurse bool) {
|
||||
tag := field.Tag.Get("boil")
|
||||
name = field.Name
|
||||
|
||||
|
@ -419,24 +407,15 @@ func getBoilTag(field reflect.StructField, titleCases map[string]string) (name s
|
|||
return name, false
|
||||
}
|
||||
|
||||
var ok bool
|
||||
ind := strings.IndexByte(tag, ',')
|
||||
if ind == -1 {
|
||||
name, ok = titleCases[tag]
|
||||
if !ok {
|
||||
name = strmangle.TitleCase(tag)
|
||||
}
|
||||
return name, false
|
||||
return strmangle.TitleCase(tag), false
|
||||
} else if ind == 0 {
|
||||
return name, true
|
||||
}
|
||||
|
||||
nameFragment := tag[:ind]
|
||||
name, ok = titleCases[nameFragment]
|
||||
if !ok {
|
||||
name = strmangle.TitleCase(nameFragment)
|
||||
}
|
||||
return name, true
|
||||
return strmangle.TitleCase(nameFragment), true
|
||||
}
|
||||
|
||||
func makeCacheKey(typ string, cols []string) string {
|
||||
|
@ -452,17 +431,12 @@ func makeCacheKey(typ string, cols []string) string {
|
|||
}
|
||||
|
||||
// GetStructValues returns the values (as interface) of the matching columns in obj
|
||||
func GetStructValues(obj interface{}, titleCases map[string]string, columns ...string) []interface{} {
|
||||
func GetStructValues(obj interface{}, columns ...string) []interface{} {
|
||||
ret := make([]interface{}, len(columns))
|
||||
val := reflect.Indirect(reflect.ValueOf(obj))
|
||||
|
||||
for i, c := range columns {
|
||||
var fieldName string
|
||||
if titleCases == nil {
|
||||
fieldName = strmangle.TitleCase(c)
|
||||
} else {
|
||||
fieldName = titleCases[c]
|
||||
}
|
||||
fieldName := strmangle.TitleCase(c)
|
||||
field := val.FieldByName(fieldName)
|
||||
if !field.IsValid() {
|
||||
panic(fmt.Sprintf("unable to find field with name: %s\n%#v", fieldName, obj))
|
||||
|
@ -474,19 +448,13 @@ func GetStructValues(obj interface{}, titleCases map[string]string, columns ...s
|
|||
}
|
||||
|
||||
// GetSliceValues returns the values (as interface) of the matching columns in obj.
|
||||
func GetSliceValues(slice []interface{}, titleCases map[string]string, columns ...string) []interface{} {
|
||||
func GetSliceValues(slice []interface{}, columns ...string) []interface{} {
|
||||
ret := make([]interface{}, len(slice)*len(columns))
|
||||
|
||||
for i, obj := range slice {
|
||||
val := reflect.Indirect(reflect.ValueOf(obj))
|
||||
for j, c := range columns {
|
||||
var fieldName string
|
||||
if titleCases == nil {
|
||||
fieldName = strmangle.TitleCase(c)
|
||||
} else {
|
||||
fieldName = titleCases[c]
|
||||
}
|
||||
|
||||
fieldName := strmangle.TitleCase(c)
|
||||
field := val.FieldByName(fieldName)
|
||||
if !field.IsValid() {
|
||||
panic(fmt.Sprintf("unable to find field with name: %s\n%#v", fieldName, obj))
|
||||
|
@ -499,7 +467,7 @@ func GetSliceValues(slice []interface{}, titleCases map[string]string, columns .
|
|||
}
|
||||
|
||||
// GetStructPointers returns a slice of pointers to the matching columns in obj
|
||||
func GetStructPointers(obj interface{}, titleCases map[string]string, columns ...string) []interface{} {
|
||||
func GetStructPointers(obj interface{}, columns ...string) []interface{} {
|
||||
val := reflect.ValueOf(obj).Elem()
|
||||
|
||||
var ln int
|
||||
|
@ -513,14 +481,7 @@ func GetStructPointers(obj interface{}, titleCases map[string]string, columns ..
|
|||
} else {
|
||||
ln = len(columns)
|
||||
getField = func(v reflect.Value, i int) reflect.Value {
|
||||
var fieldName string
|
||||
if titleCases == nil {
|
||||
fieldName = strmangle.TitleCase(columns[i])
|
||||
} else {
|
||||
fieldName = titleCases[columns[i]]
|
||||
}
|
||||
|
||||
return v.FieldByName(fieldName)
|
||||
return v.FieldByName(strmangle.TitleCase(columns[i]))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ func TestMakeStructMapping(t *testing.T) {
|
|||
} `boil:",bind"`
|
||||
}{}
|
||||
|
||||
got := makeStructMapping(reflect.TypeOf(testStruct), nil)
|
||||
got := makeStructMapping(reflect.TypeOf(testStruct))
|
||||
|
||||
expectMap := map[string]uint64{
|
||||
"Different": testMakeMapping(0),
|
||||
|
@ -189,16 +189,6 @@ func TestGetBoilTag(t *testing.T) {
|
|||
Nose string
|
||||
}
|
||||
|
||||
var testTitleCases = map[string]string{
|
||||
"test_one": "TestOne",
|
||||
"test_two": "TestTwo",
|
||||
"middle_name": "MiddleName",
|
||||
"awesome_name": "AwesomeName",
|
||||
"age": "Age",
|
||||
"face": "Face",
|
||||
"nose": "Nose",
|
||||
}
|
||||
|
||||
var structFields []reflect.StructField
|
||||
typ := reflect.TypeOf(TestStruct{})
|
||||
removeOk := func(thing reflect.StructField, ok bool) reflect.StructField {
|
||||
|
@ -228,7 +218,7 @@ func TestGetBoilTag(t *testing.T) {
|
|||
{"Nose", false},
|
||||
}
|
||||
for i, s := range structFields {
|
||||
name, recurse := getBoilTag(s, testTitleCases)
|
||||
name, recurse := getBoilTag(s)
|
||||
if expect[i].Name != name {
|
||||
t.Errorf("Invalid name, expect %q, got %q", expect[i].Name, name)
|
||||
}
|
||||
|
@ -665,7 +655,7 @@ func TestGetStructValues(t *testing.T) {
|
|||
NullBool: null.NewBool(true, false),
|
||||
}
|
||||
|
||||
vals := GetStructValues(&o, nil, "title_thing", "name", "id", "stuff", "things", "time", "null_bool")
|
||||
vals := GetStructValues(&o, "title_thing", "name", "id", "stuff", "things", "time", "null_bool")
|
||||
if vals[0].(string) != "patrick" {
|
||||
t.Errorf("Want test, got %s", vals[0])
|
||||
}
|
||||
|
@ -704,7 +694,7 @@ func TestGetSliceValues(t *testing.T) {
|
|||
in[0] = o[0]
|
||||
in[1] = o[1]
|
||||
|
||||
vals := GetSliceValues(in, nil, "id", "name")
|
||||
vals := GetSliceValues(in, "id", "name")
|
||||
if got := vals[0].(int); got != 5 {
|
||||
t.Error(got)
|
||||
}
|
||||
|
@ -729,7 +719,7 @@ func TestGetStructPointers(t *testing.T) {
|
|||
Title: "patrick",
|
||||
}
|
||||
|
||||
ptrs := GetStructPointers(&o, nil, "title", "id")
|
||||
ptrs := GetStructPointers(&o, "title", "id")
|
||||
*ptrs[0].(*string) = "test"
|
||||
if o.Title != "test" {
|
||||
t.Errorf("Expected test, got %s", o.Title)
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -150,6 +151,13 @@ func Singular(name string) string {
|
|||
return buf.String()
|
||||
}
|
||||
|
||||
// titleCaseCache holds the mapping of title cases.
|
||||
// Example: map["MyWord"] == "my_word"
|
||||
var (
|
||||
mut sync.RWMutex
|
||||
titleCaseCache = map[string]string{}
|
||||
)
|
||||
|
||||
// TitleCase changes a snake-case variable name
|
||||
// into a go styled object variable name of "ColumnName".
|
||||
// titleCase also fully uppercases "ID" components of names, for example
|
||||
|
@ -158,6 +166,14 @@ func Singular(name string) string {
|
|||
// Note: This method is ugly because it has been highly optimized,
|
||||
// we found that it was a fairly large bottleneck when we were using regexp.
|
||||
func TitleCase(n string) string {
|
||||
// Attempt to fetch from cache
|
||||
mut.RLock()
|
||||
val, ok := titleCaseCache[n]
|
||||
mut.RUnlock()
|
||||
if ok {
|
||||
return val
|
||||
}
|
||||
|
||||
ln := len(n)
|
||||
name := []byte(n)
|
||||
buf := GetBuffer()
|
||||
|
@ -219,6 +235,12 @@ func TitleCase(n string) string {
|
|||
|
||||
ret := buf.String()
|
||||
PutBuffer(buf)
|
||||
|
||||
// Cache the title case result
|
||||
mut.Lock()
|
||||
titleCaseCache[n] = ret
|
||||
mut.Unlock()
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
@ -264,14 +286,10 @@ func CamelCase(name string) string {
|
|||
|
||||
// TitleCaseIdentifier splits on dots and then titlecases each fragment.
|
||||
// map titleCase (split c ".")
|
||||
func TitleCaseIdentifier(id string, titleCases map[string]string) string {
|
||||
func TitleCaseIdentifier(id string) string {
|
||||
nextDot := strings.IndexByte(id, '.')
|
||||
if nextDot < 0 {
|
||||
titled, ok := titleCases[id]
|
||||
if !ok {
|
||||
titled = TitleCase(id)
|
||||
}
|
||||
return titled
|
||||
return TitleCase(id)
|
||||
}
|
||||
|
||||
buf := GetBuffer()
|
||||
|
@ -283,10 +301,7 @@ func TitleCaseIdentifier(id string, titleCases map[string]string) string {
|
|||
fmt.Println(lastDot, nextDot)
|
||||
fragment := id[lastDot:nextDot]
|
||||
|
||||
titled, ok := titleCases[fragment]
|
||||
if !ok {
|
||||
titled = TitleCase(fragment)
|
||||
}
|
||||
titled := TitleCase(fragment)
|
||||
|
||||
if addDots {
|
||||
buf.WriteByte('.')
|
||||
|
|
|
@ -242,7 +242,7 @@ func TestTitleCaseIdentifier(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, test := range tests {
|
||||
if out := TitleCaseIdentifier(test.In, nil); out != test.Out {
|
||||
if out := TitleCaseIdentifier(test.In); out != test.Out {
|
||||
t.Errorf("[%d] (%s) Out was wrong: %q, want: %q", i, test.In, out, test.Out)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func (q {{$varNameSingular}}Query) One() (*{{$tableNameSingular}}, error) {
|
|||
|
||||
boil.SetLimit(q.Query, 1)
|
||||
|
||||
err := q.BindFast(o, {{$varNameSingular}}TitleCases)
|
||||
err := q.Bind(o)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, sql.ErrNoRows
|
||||
|
@ -47,7 +47,7 @@ func (q {{$varNameSingular}}Query) AllP() {{$tableNameSingular}}Slice {
|
|||
func (q {{$varNameSingular}}Query) All() ({{$tableNameSingular}}Slice, error) {
|
||||
var o {{$tableNameSingular}}Slice
|
||||
|
||||
err := q.BindFast(&o, {{$varNameSingular}}TitleCases)
|
||||
err := q.Bind(&o)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "{{.PkgName}}: failed to assign all query results to {{$tableNameSingular}} slice")
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ func ({{$varNameSingular}}L) Load{{.Function.Name}}(e boil.Executor, singular bo
|
|||
defer results.Close()
|
||||
|
||||
var resultSlice []*{{.ForeignTable.NameGo}}
|
||||
if err = boil.BindFast(results, &resultSlice, {{.ForeignTable.Name | singular | camelCase}}TitleCases); err != nil {
|
||||
if err = boil.Bind(results, &resultSlice); err != nil {
|
||||
return errors.Wrap(err, "failed to bind eager loaded slice {{.ForeignTable.NameGo}}")
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
|
|||
return errors.Wrap(err, "failed to plebian-bind eager loaded slice {{.ForeignTable}}")
|
||||
}
|
||||
{{else -}}
|
||||
if err = boil.BindFast(results, &resultSlice, {{.ForeignTable | singular | camelCase}}TitleCases); err != nil {
|
||||
if err = boil.Bind(results, &resultSlice); err != nil {
|
||||
return errors.Wrap(err, "failed to bind eager loaded slice {{.ForeignTable}}")
|
||||
}
|
||||
{{end}}
|
||||
|
|
|
@ -34,7 +34,7 @@ func Find{{$tableNameSingular}}(exec boil.Executor, {{$pkArgs}}, selectCols ...s
|
|||
|
||||
q := boil.SQL(exec, query, {{$pkNames | join ", "}})
|
||||
|
||||
err := q.BindFast({{$varNameSingular}}Obj, {{$varNameSingular}}TitleCases)
|
||||
err := q.Bind({{$varNameSingular}}Obj)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, sql.ErrNoRows
|
||||
|
|
|
@ -53,10 +53,10 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
|||
{{if .UseLastInsertID}}
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, ins)
|
||||
fmt.Fprintln(boil.DebugWriter, boil.GetStructValues(o, {{$varNameSingular}}TitleCases, wl...))
|
||||
fmt.Fprintln(boil.DebugWriter, boil.GetStructValues(o, wl...))
|
||||
}
|
||||
|
||||
result, err := exec.Exec(ins, boil.GetStructValues(o, {{$varNameSingular}}TitleCases, wl...)...)
|
||||
result, err := exec.Exec(ins, boil.GetStructValues(o, wl...)...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to insert into {{.Table.Name}}")
|
||||
}
|
||||
|
@ -77,21 +77,21 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
|||
}
|
||||
|
||||
sel := fmt.Sprintf(`SELECT %s FROM {{.Table.Name}} WHERE %s`, strings.Join(returnColumns, `","`), strmangle.WhereClause(1, {{$varNameSingular}}AutoIncPrimaryKeys))
|
||||
err = exec.QueryRow(sel, lastID).Scan(boil.GetStructPointers(o, {{$varNameSingular}}TitleCases, returnColumns...))
|
||||
err = exec.QueryRow(sel, lastID).Scan(boil.GetStructPointers(o, returnColumns...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to populate default values for {{.Table.Name}}")
|
||||
}
|
||||
{{else}}
|
||||
if len(returnColumns) != 0 {
|
||||
ins = ins + fmt.Sprintf(` RETURNING %s`, strings.Join(returnColumns, ","))
|
||||
err = exec.QueryRow(ins, boil.GetStructValues(o, {{$varNameSingular}}TitleCases, wl...)...).Scan(boil.GetStructPointers(o, {{$varNameSingular}}TitleCases, returnColumns...)...)
|
||||
err = exec.QueryRow(ins, boil.GetStructValues(o, wl...)...).Scan(boil.GetStructPointers(o, returnColumns...)...)
|
||||
} else {
|
||||
_, err = exec.Exec(ins, boil.GetStructValues(o, {{$varNameSingular}}TitleCases, wl...)...)
|
||||
_, err = exec.Exec(ins, boil.GetStructValues(o, wl...)...)
|
||||
}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, ins)
|
||||
fmt.Fprintln(boil.DebugWriter, boil.GetStructValues(o, {{$varNameSingular}}TitleCases, wl...))
|
||||
fmt.Fprintln(boil.DebugWriter, boil.GetStructValues(o, wl...))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -53,7 +53,7 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string
|
|||
}
|
||||
|
||||
query = fmt.Sprintf(`UPDATE {{.Table.Name}} SET %s WHERE %s`, strmangle.SetParamNames(wl), strmangle.WhereClause(len(wl)+1, {{$varNameSingular}}PrimaryKeyColumns))
|
||||
values = boil.GetStructValues(o, {{$varNameSingular}}TitleCases, wl...)
|
||||
values = boil.GetStructValues(o, wl...)
|
||||
values = append(values, {{.Table.PKey.Columns | stringMap .StringFuncs.titleCase | prefixStringSlice "o." | join ", "}})
|
||||
|
||||
if boil.DebugMode {
|
||||
|
|
|
@ -58,16 +58,16 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, updateOnConflict boo
|
|||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, query)
|
||||
fmt.Fprintln(boil.DebugWriter, boil.GetStructValues(o, {{$varNameSingular}}TitleCases, whitelist...))
|
||||
fmt.Fprintln(boil.DebugWriter, boil.GetStructValues(o, whitelist...))
|
||||
}
|
||||
|
||||
{{- if .UseLastInsertID}}
|
||||
return errors.New("don't know how to do this yet")
|
||||
{{- else}}
|
||||
if len(ret) != 0 {
|
||||
err = exec.QueryRow(query, boil.GetStructValues(o, {{$varNameSingular}}TitleCases, whitelist...)...).Scan(boil.GetStructPointers(o, {{$varNameSingular}}TitleCases, ret...)...)
|
||||
err = exec.QueryRow(query, boil.GetStructValues(o, whitelist...)...).Scan(boil.GetStructPointers(o, ret...)...)
|
||||
} else {
|
||||
_, err = exec.Exec(query, boil.GetStructValues(o, {{$varNameSingular}}TitleCases, whitelist...)...)
|
||||
_, err = exec.Exec(query, boil.GetStructValues(o, whitelist...)...)
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ func (o *{{$tableNameSingular}}Slice) ReloadAll(exec boil.Executor) error {
|
|||
|
||||
q := boil.SQL(exec, sql, args...)
|
||||
|
||||
err := q.BindFast(&{{$varNamePlural}}, {{$varNameSingular}}TitleCases)
|
||||
err := q.Bind(&{{$varNamePlural}})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to reload all in {{$tableNameSingular}}Slice")
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue