Allow binding to []struct, not just []*struct

This commit is contained in:
Aaron L 2016-09-03 10:43:32 -07:00
parent 08dc7a5cc1
commit e0ea582e37
2 changed files with 100 additions and 2 deletions

View file

@ -188,7 +188,7 @@ func bind(rows *sql.Rows, obj interface{}, structType, sliceType reflect.Type, b
var ptrSlice reflect.Value var ptrSlice reflect.Value
switch bkind { switch bkind {
case kindPtrSliceStruct: case kindSliceStruct, kindPtrSliceStruct:
ptrSlice = reflect.Indirect(reflect.ValueOf(obj)) ptrSlice = reflect.Indirect(reflect.ValueOf(obj))
} }
@ -211,6 +211,11 @@ func bind(rows *sql.Rows, obj interface{}, structType, sliceType reflect.Type, b
mut.Unlock() mut.Unlock()
} }
var oneStruct reflect.Value
if bkind == kindSliceStruct {
oneStruct = reflect.Indirect(reflect.New(structType))
}
foundOne := false foundOne := false
for rows.Next() { for rows.Next() {
foundOne = true foundOne = true
@ -220,6 +225,8 @@ func bind(rows *sql.Rows, obj interface{}, structType, sliceType reflect.Type, b
switch bkind { switch bkind {
case kindStruct: case kindStruct:
pointers = ptrsFromMapping(reflect.Indirect(reflect.ValueOf(obj)), mapping) pointers = ptrsFromMapping(reflect.Indirect(reflect.ValueOf(obj)), mapping)
case kindSliceStruct:
pointers = ptrsFromMapping(oneStruct, mapping)
case kindPtrSliceStruct: case kindPtrSliceStruct:
newStruct = reflect.New(structType) newStruct = reflect.New(structType)
pointers = ptrsFromMapping(reflect.Indirect(newStruct), mapping) pointers = ptrsFromMapping(reflect.Indirect(newStruct), mapping)
@ -233,6 +240,8 @@ func bind(rows *sql.Rows, obj interface{}, structType, sliceType reflect.Type, b
} }
switch bkind { switch bkind {
case kindSliceStruct:
ptrSlice.Set(reflect.Append(ptrSlice, oneStruct))
case kindPtrSliceStruct: case kindPtrSliceStruct:
ptrSlice.Set(reflect.Append(ptrSlice, newStruct)) ptrSlice.Set(reflect.Append(ptrSlice, newStruct))
} }

View file

@ -35,7 +35,96 @@ type mockRowMaker struct {
rows []driver.Value rows []driver.Value
} }
func TestBind(t *testing.T) { func TestBindStruct(t *testing.T) {
t.Parallel()
testResults := struct {
ID int
Name string `boil:"test"`
}{}
query := &Query{
from: []string{"fun"},
}
db, mock, err := sqlmock.New()
if err != nil {
t.Error(err)
}
ret := sqlmock.NewRows([]string{"id", "test"})
ret.AddRow(driver.Value(int64(35)), driver.Value("pat"))
mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret)
SetExecutor(query, db)
err = query.Bind(&testResults)
if err != nil {
t.Error(err)
}
if id := testResults.ID; id != 35 {
t.Error("wrong ID:", id)
}
if name := testResults.Name; name != "pat" {
t.Error("wrong name:", name)
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Error(err)
}
}
func TestBindSlice(t *testing.T) {
t.Parallel()
testResults := []struct {
ID int
Name string `boil:"test"`
}{}
query := &Query{
from: []string{"fun"},
}
db, mock, err := sqlmock.New()
if err != nil {
t.Error(err)
}
ret := sqlmock.NewRows([]string{"id", "test"})
ret.AddRow(driver.Value(int64(35)), driver.Value("pat"))
ret.AddRow(driver.Value(int64(12)), driver.Value("cat"))
mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret)
SetExecutor(query, db)
err = query.Bind(&testResults)
if err != nil {
t.Error(err)
}
if len(testResults) != 2 {
t.Fatal("wrong number of results:", len(testResults))
}
if id := testResults[0].ID; id != 35 {
t.Error("wrong ID:", id)
}
if name := testResults[0].Name; name != "pat" {
t.Error("wrong name:", name)
}
if id := testResults[1].ID; id != 12 {
t.Error("wrong ID:", id)
}
if name := testResults[1].Name; name != "cat" {
t.Error("wrong name:", name)
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Error(err)
}
}
func TestBindPtrSlice(t *testing.T) {
t.Parallel() t.Parallel()
testResults := []*struct { testResults := []*struct {