Added more insert test, added comments

* Added IsZeroValue helper
This commit is contained in:
Patrick O'brien 2016-07-08 01:59:07 +10:00
parent 0275677216
commit 08d168605f
4 changed files with 136 additions and 20 deletions

View file

@ -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))

View file

@ -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()

View file

@ -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 {

View file

@ -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.
*/
}