Added more insert test, added comments
* Added IsZeroValue helper
This commit is contained in:
parent
0275677216
commit
08d168605f
4 changed files with 136 additions and 20 deletions
|
@ -159,6 +159,24 @@ func checkType(obj interface{}) (reflect.Type, bool, error) {
|
|||
return typ, isSlice, nil
|
||||
}
|
||||
|
||||
// IsZeroValue checks if the variables with matching columns in obj are zero values
|
||||
func isZeroValue(obj interface{}, columns ...string) bool {
|
||||
val := reflect.ValueOf(obj)
|
||||
for _, c := range columns {
|
||||
field := val.FieldByName(strmangle.TitleCase(c))
|
||||
if !field.IsValid() {
|
||||
panic(fmt.Sprintf("Unable to find variable with column name %s", c))
|
||||
}
|
||||
|
||||
zv := reflect.Zero(field.Type())
|
||||
if !reflect.DeepEqual(field.Interface(), zv.Interface()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// GetStructValues returns the values (as interface) of the matching columns in obj
|
||||
func GetStructValues(obj interface{}, columns ...string) []interface{} {
|
||||
ret := make([]interface{}, len(columns))
|
||||
|
|
|
@ -19,6 +19,39 @@ func TestBindAll(t *testing.T) {
|
|||
t.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func TestIsZeroValue(t *testing.T) {
|
||||
o := struct {
|
||||
A []byte
|
||||
B time.Time
|
||||
C null.Time
|
||||
D null.Int64
|
||||
E int64
|
||||
}{}
|
||||
|
||||
if !isZeroValue(o, "A", "B", "C", "D", "E") {
|
||||
t.Errorf("Expected all values to be zero values: %#v", o)
|
||||
}
|
||||
|
||||
colNames := []string{"A", "B", "C", "D", "E"}
|
||||
for _, c := range colNames {
|
||||
if !isZeroValue(o, c) {
|
||||
t.Errorf("Expected %s to be zero value: %#v", c, o)
|
||||
}
|
||||
}
|
||||
|
||||
o.A = []byte("asdf")
|
||||
o.B = time.Now()
|
||||
o.C = null.NewTime(time.Now(), false)
|
||||
o.D = null.NewInt64(2, false)
|
||||
o.E = 5
|
||||
|
||||
for _, c := range colNames {
|
||||
if isZeroValue(o, c) {
|
||||
t.Errorf("Expected %s to be non-zero value: %#v", c, o)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStructValues(t *testing.T) {
|
||||
t.Parallel()
|
||||
timeThing := time.Now()
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
{{- $tableNameSingular := .Table.Name | singular | titleCase -}}
|
||||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
// Insert a single record.
|
||||
func (o *{{$tableNameSingular}}) Insert(whitelist ... string) error {
|
||||
return o.InsertX(boil.GetDB(), whitelist...)
|
||||
func (o *{{$tableNameSingular}}) Insert(include ... string) error {
|
||||
return o.InsertX(boil.GetDB(), include...)
|
||||
}
|
||||
|
||||
// InsertX a single record using an executor.
|
||||
func (o *{{$tableNameSingular}}) InsertX(exec boil.Executor, whitelist ... string) error {
|
||||
func (o *{{$tableNameSingular}}) InsertX(exec boil.Executor, include ... string) error {
|
||||
if o == nil {
|
||||
return errors.New("{{.PkgName}}: no {{.Table.Name}} provided for insertion")
|
||||
}
|
||||
|
||||
var wl []string
|
||||
var includes []string
|
||||
|
||||
wl = append(wl, whitelist...)
|
||||
if len(whitelist) == 0 {
|
||||
wl = append(wl, {{$varNameSingular}}ColumnsWithoutDefault...)
|
||||
includes = append(includes, include...)
|
||||
if len(include) == 0 {
|
||||
includes = append(includes, {{$varNameSingular}}ColumnsWithoutDefault...)
|
||||
}
|
||||
|
||||
wl = append(boil.NonZeroDefaultSet({{$varNameSingular}}ColumnsWithDefault, o), wl...)
|
||||
wl = boil.SortByKeys({{$varNameSingular}}Columns, wl)
|
||||
includes = append(boil.NonZeroDefaultSet({{$varNameSingular}}ColumnsWithDefault, o), includes...)
|
||||
includes = boil.SortByKeys({{$varNameSingular}}Columns, includes)
|
||||
|
||||
// Only return the columns with default values that are not in the insert whitelist
|
||||
returnColumns := boil.SetComplement({{$varNameSingular}}ColumnsWithDefault, wl)
|
||||
// Only return the columns with default values that are not in the insert include
|
||||
returnColumns := boil.SetComplement({{$varNameSingular}}ColumnsWithDefault, includes)
|
||||
|
||||
var err error
|
||||
if err := o.doBeforeCreateHooks(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ins := fmt.Sprintf(`INSERT INTO {{.Table.Name}} ("%s") VALUES (%s)`, strings.Join(wl, `","`), boil.GenerateParamFlags(len(wl), 1))
|
||||
ins := fmt.Sprintf(`INSERT INTO {{.Table.Name}} ("%s") VALUES (%s)`, strings.Join(includes, `","`), boil.GenerateParamFlags(len(includes), 1))
|
||||
|
||||
{{if driverUsesLastInsertID .DriverName}}
|
||||
if len(returnColumns) != 0 {
|
||||
result, err := exec.Exec(ins, boil.GetStructValues(o, wl...)...)
|
||||
result, err := exec.Exec(ins, boil.GetStructValues(o, includes...)...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("{{.PkgName}}: unable to insert into {{.Table.Name}}: %s", err)
|
||||
}
|
||||
|
||||
lastId, err := result.lastInsertId()
|
||||
if err != nil || lastId == 0 {
|
||||
sel := fmt.Sprintf(`SELECT %s FROM {{.Table.Name}} WHERE %s`, strings.Join(returnColumns, `","`), boil.WhereClause(wl))
|
||||
rows, err := exec.Query(sel, boil.GetStructValues(o, wl...)...)
|
||||
sel := fmt.Sprintf(`SELECT %s FROM {{.Table.Name}} WHERE %s`, strings.Join(returnColumns, `","`), boil.WhereClause(includes))
|
||||
rows, err := exec.Query(sel, boil.GetStructValues(o, includes...)...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("{{.PkgName}}: unable to insert into {{.Table.Name}}: %s", err)
|
||||
}
|
||||
|
@ -59,19 +59,19 @@ func (o *{{$tableNameSingular}}) InsertX(exec boil.Executor, whitelist ... strin
|
|||
sel := fmt.Sprintf(`SELECT %s FROM {{.Table.Name}} WHERE %s=$1`, strings.Join(returnColumns, ","), {{$varNameSingular}}AutoIncPrimaryKey, lastId)
|
||||
}
|
||||
} else {
|
||||
_, err = exec.Exec(ins, boil.GetStructValues(o, wl...)...)
|
||||
_, err = exec.Exec(ins, boil.GetStructValues(o, includes...)...)
|
||||
}
|
||||
{{else}}
|
||||
if len(returnColumns) != 0 {
|
||||
ins = ins + fmt.Sprintf(` RETURNING %s`, strings.Join(returnColumns, ","))
|
||||
err = exec.QueryRow(ins, boil.GetStructValues(o, wl...)...).Scan(boil.GetStructPointers(o, returnColumns...)...)
|
||||
err = exec.QueryRow(ins, boil.GetStructValues(o, includes...)...).Scan(boil.GetStructPointers(o, returnColumns...)...)
|
||||
} else {
|
||||
_, err = exec.Exec(ins, {{.Table.Columns | columnNames | stringMap .StringFuncs.titleCase | prefixStringSlice "o." | join ", "}})
|
||||
}
|
||||
{{end}}
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintln(boil.DebugWriter, ins, boil.GetStructValues(o, wl...))
|
||||
fmt.Fprintln(boil.DebugWriter, ins, boil.GetStructValues(o, includes...))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -26,7 +26,17 @@ func Test{{$tableNamePlural}}Insert(t *testing.T) {
|
|||
{{$varNameSingular}}CompareVals(o[i], j[i], t)
|
||||
}
|
||||
|
||||
// Ensure we can store zero-valued object successfully.
|
||||
/**
|
||||
* Edge case test for:
|
||||
* No includes specified, all zero values.
|
||||
*
|
||||
* Expected result:
|
||||
* Columns with default values set to their default values.
|
||||
* Columns without default values set to their zero value.
|
||||
*/
|
||||
|
||||
{{$varNamePlural}}DeleteAllRows(t)
|
||||
|
||||
item := &{{$tableNameSingular}}{}
|
||||
if err = item.Insert(); err != nil {
|
||||
t.Errorf("Unable to insert zero-value item {{$tableNameSingular}}:\n%#v\nErr: %s", item, err)
|
||||
|
@ -36,7 +46,7 @@ func Test{{$tableNamePlural}}Insert(t *testing.T) {
|
|||
// Ensure the auto increment columns are returned in the object
|
||||
{{range .}}
|
||||
if item.{{titleCase .}} <= 0 {
|
||||
t.Errorf("Expected the auto-increment primary key to be greater than 0, got: %d", item.{{titleCase .}})
|
||||
t.Errorf("Expected the auto-increment columns to be greater than 0, got: %d", item.{{titleCase .}})
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
@ -106,4 +116,59 @@ func Test{{$tableNamePlural}}Insert(t *testing.T) {
|
|||
{{- end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
/**
|
||||
* Edge case test for:
|
||||
* No includes specified, all non-zero values.
|
||||
*
|
||||
* Expected result:
|
||||
* Non-zero auto-increment column values ignored by insert helper.
|
||||
* Object updated with correct auto-increment values.
|
||||
* All other column values in object remain.
|
||||
*/
|
||||
|
||||
{{$varNamePlural}}DeleteAllRows(t)
|
||||
|
||||
item = &{{$tableNameSingular}}{}
|
||||
if err = item.Insert(); err != nil {
|
||||
t.Errorf("Unable to insert zero-value item {{$tableNameSingular}}:\n%#v\nErr: %s", item, err)
|
||||
}
|
||||
|
||||
/**
|
||||
* Edge case test for:
|
||||
* Auto-increment columns and nullable columns includes specified, all zero values.
|
||||
*
|
||||
* Expected result:
|
||||
* Auto-increment value inserted and nullable column values inserted.
|
||||
* Default values for nullable columns should NOT be present in returned object.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edge case test for:
|
||||
* Auto-increment columns and nullable columns includes specified, all non-zero values.
|
||||
*
|
||||
* Expected result:
|
||||
* Auto-increment value inserted and nullable column values inserted.
|
||||
* Default values for nullable columns should NOT be present in returned object.
|
||||
* Should be no zero values anywhere.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edge case test for:
|
||||
* Non-nullable columns includes specified, all zero values.
|
||||
*
|
||||
* Expected result:
|
||||
* Auto-increment values ignored by insert helper.
|
||||
* Object updated with correct auto-increment values.
|
||||
* All non-nullable columns should be returned as zero values, regardless of default values.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edge case test for:
|
||||
* Non-nullable columns includes specified, all non-zero values.
|
||||
*
|
||||
* Expected result:
|
||||
* Auto-increment values ignored by insert helper.
|
||||
* Object updated with correct auto-increment values.
|
||||
*/
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue