Skip to content

Commit

Permalink
Merge pull request doug-martin#20 from ruzz311/scanstruct-embedded-ptr
Browse files Browse the repository at this point in the history
Fix issue doug-martin#19 - Exec.ScanStruct does not allow embedded pointers
  • Loading branch information
ruzz311 committed Jan 5, 2016
2 parents 7f2d21e + 753c248 commit a96f4ed
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 52 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ language: go
go:
- 1.3
- 1.4
- 1.5
- tip


Expand Down
8 changes: 6 additions & 2 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v3.1.2

* Fixing ScanStruct issue with embedded pointers in crud_exec [#20](https://github.com/doug-martin/goqu/pull/20) - [@ruzz311](https://github.com/ruzz311)

## v3.1.1

* Fixing race condition with struct_map_cache in crud_exec [#18](https://github.com/doug-martin/goqu/pull/18) - [@andymoon](https://github.com/andymoon), [@aheuermann](https://github.com/aheuermann)
Expand All @@ -8,7 +12,7 @@
* Fix an issue with a nil pointer access on the inserts and updates.
* Allowing ScanStructs to take a struct with an embedded pointer to a struct.
* Change to check if struct is Anonymous when recursing through an embedded struct.
* Updated to use the lastest version of github.com/DATA-DOG/go-sqlmock.
* Updated to use the latest version of github.com/DATA-DOG/go-sqlmock.

## v3.0.1

Expand Down Expand Up @@ -80,4 +84,4 @@

## v0.0.1

* Initial release
* Initial release
1 change: 1 addition & 0 deletions crud_exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ func assignVals(i interface{}, results []Record, cm columnMap) error {
switch val.Kind() {
case reflect.Struct:
result := results[0]
initEmbeddedPtr(val)
for name, data := range cm {
src, ok := result[name]
if ok {
Expand Down
36 changes: 36 additions & 0 deletions crud_exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ type testComposedCrudActionItem struct {
Age int64 `db:"age"`
}

type testEmbeddedPtrCrudActionItem struct {
*testCrudActionItem
PhoneNumber string `db:"phone_number"`
Age int64 `db:"age"`
}

type crudExecTest struct {
suite.Suite
}
Expand Down Expand Up @@ -74,6 +80,10 @@ func (me *crudExecTest) TestScanStructs() {
WithArgs().
WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).FromCSVString("111 Test Addr,Test1,111-111-1111,20\n211 Test Addr,Test2,222-222-2222,30"))

mock.ExpectQuery(`SELECT \* FROM "items"`).
WithArgs().
WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).FromCSVString("111 Test Addr,Test1,111-111-1111,20\n211 Test Addr,Test2,222-222-2222,30"))

mock.ExpectQuery(`SELECT \* FROM "items"`).
WithArgs().
WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).FromCSVString("111 Test Addr,Test1\n211 Test Addr,Test2"))
Expand Down Expand Up @@ -129,6 +139,19 @@ func (me *crudExecTest) TestScanStructs() {
assert.Equal(t, composedPointers[1].PhoneNumber, "222-222-2222")
assert.Equal(t, composedPointers[1].Age, 30)

var embeddedPtrs []*testEmbeddedPtrCrudActionItem
assert.NoError(t, exec.ScanStructs(&embeddedPtrs))
assert.Len(t, embeddedPtrs, 2)
assert.Equal(t, embeddedPtrs[0].Address, "111 Test Addr")
assert.Equal(t, embeddedPtrs[0].Name, "Test1")
assert.Equal(t, embeddedPtrs[0].PhoneNumber, "111-111-1111")
assert.Equal(t, embeddedPtrs[0].Age, 20)

assert.Equal(t, embeddedPtrs[1].Address, "211 Test Addr")
assert.Equal(t, embeddedPtrs[1].Name, "Test2")
assert.Equal(t, embeddedPtrs[1].PhoneNumber, "222-222-2222")
assert.Equal(t, embeddedPtrs[1].Age, 30)

var noTags []testCrudActionNoTagsItem
assert.NoError(t, exec.ScanStructs(&noTags))
assert.Len(t, noTags, 2)
Expand Down Expand Up @@ -156,6 +179,10 @@ func (me *crudExecTest) TestScanStruct() {
WithArgs().
WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).FromCSVString("111 Test Addr,Test1,111-111-1111,20"))

mock.ExpectQuery(`SELECT \* FROM "items"`).
WithArgs().
WillReturnRows(sqlmock.NewRows([]string{"address", "name", "phone_number", "age"}).FromCSVString("111 Test Addr,Test1,111-111-1111,20"))

mock.ExpectQuery(`SELECT \* FROM "items"`).
WithArgs().
WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).FromCSVString("111 Test Addr,Test1"))
Expand Down Expand Up @@ -190,6 +217,15 @@ func (me *crudExecTest) TestScanStruct() {
assert.Equal(t, composed.PhoneNumber, "111-111-1111")
assert.Equal(t, composed.Age, 20)

var embeddedPtr testEmbeddedPtrCrudActionItem
found, err = exec.ScanStruct(&embeddedPtr)
assert.NoError(t, err)
assert.True(t, found)
assert.Equal(t, embeddedPtr.Address, "111 Test Addr")
assert.Equal(t, embeddedPtr.Name, "Test1")
assert.Equal(t, embeddedPtr.PhoneNumber, "111-111-1111")
assert.Equal(t, embeddedPtr.Age, 20)

var noTag testCrudActionNoTagsItem
found, err = exec.ScanStruct(&noTag)
assert.NoError(t, err)
Expand Down
56 changes: 28 additions & 28 deletions dataset_insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,24 +61,24 @@ func (me *datasetTest) TestInsertSqlWithStructs() {
func (me *datasetTest) TestInsertSqlWithEmbeddedStruct() {
t := me.T()
ds1 := From("items")
type phone struct {
type Phone struct {
Primary string `db:"primary_phone"`
Home string `db:"home_phone"`
}
type item struct {
phone
Phone
Address string `db:"address"`
Name string `db:"name"`
}
sql, _, err := ds1.ToInsertSql(item{Name: "Test", Address: "111 Test Addr", phone: phone{Home: "123123", Primary: "456456"}})
sql, _, err := ds1.ToInsertSql(item{Name: "Test", Address: "111 Test Addr", Phone: Phone{Home: "123123", Primary: "456456"}})
assert.NoError(t, err)
assert.Equal(t, sql, `INSERT INTO "items" ("primary_phone", "home_phone", "address", "name") VALUES ('456456', '123123', '111 Test Addr', 'Test')`)

sql, _, err = ds1.ToInsertSql(
item{Address: "111 Test Addr", Name: "Test1", phone: phone{Home: "123123", Primary: "456456"}},
item{Address: "211 Test Addr", Name: "Test2", phone: phone{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", phone: phone{Home: "123123", Primary: "456456"}},
item{Address: "411 Test Addr", Name: "Test4", phone: phone{Home: "123123", Primary: "456456"}},
item{Address: "111 Test Addr", Name: "Test1", Phone: Phone{Home: "123123", Primary: "456456"}},
item{Address: "211 Test Addr", Name: "Test2", Phone: Phone{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", Phone: Phone{Home: "123123", Primary: "456456"}},
item{Address: "411 Test Addr", Name: "Test4", Phone: Phone{Home: "123123", Primary: "456456"}},
)
assert.NoError(t, err)
assert.Equal(t, sql, `INSERT INTO "items" ("primary_phone", "home_phone", "address", "name") VALUES ('456456', '123123', '111 Test Addr', 'Test1'), ('456456', '123123', '211 Test Addr', 'Test2'), ('456456', '123123', '311 Test Addr', 'Test3'), ('456456', '123123', '411 Test Addr', 'Test4')`)
Expand All @@ -87,25 +87,25 @@ func (me *datasetTest) TestInsertSqlWithEmbeddedStruct() {
func (me *datasetTest) TestInsertSqlWithEmbeddedStructPtr() {
t := me.T()
ds1 := From("items")
type phone struct {
type Phone struct {
Primary string `db:"primary_phone"`
Home string `db:"home_phone"`
}
type item struct {
*phone
*Phone
Address string `db:"address"`
Name string `db:"name"`
Valuer sql.NullInt64 `db:"valuer"`
}
sql, _, err := ds1.ToInsertSql(item{Name: "Test", Address: "111 Test Addr", Valuer: sql.NullInt64{Int64: 10, Valid: true}, phone: &phone{Home: "123123", Primary: "456456"}})
sql, _, err := ds1.ToInsertSql(item{Name: "Test", Address: "111 Test Addr", Valuer: sql.NullInt64{Int64: 10, Valid: true}, Phone: &Phone{Home: "123123", Primary: "456456"}})
assert.NoError(t, err)
assert.Equal(t, sql, `INSERT INTO "items" ("primary_phone", "home_phone", "address", "name", "valuer") VALUES ('456456', '123123', '111 Test Addr', 'Test', 10)`)

sql, _, err = ds1.ToInsertSql(
item{Address: "111 Test Addr", Name: "Test1", phone: &phone{Home: "123123", Primary: "456456"}},
item{Address: "211 Test Addr", Name: "Test2", phone: &phone{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", phone: &phone{Home: "123123", Primary: "456456"}},
item{Address: "411 Test Addr", Name: "Test4", phone: &phone{Home: "123123", Primary: "456456"}},
item{Address: "111 Test Addr", Name: "Test1", Phone: &Phone{Home: "123123", Primary: "456456"}},
item{Address: "211 Test Addr", Name: "Test2", Phone: &Phone{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", Phone: &Phone{Home: "123123", Primary: "456456"}},
item{Address: "411 Test Addr", Name: "Test4", Phone: &Phone{Home: "123123", Primary: "456456"}},
)
assert.NoError(t, err)
assert.Equal(t, sql, `INSERT INTO "items" ("primary_phone", "home_phone", "address", "name", "valuer") VALUES ('456456', '123123', '111 Test Addr', 'Test1', NULL), ('456456', '123123', '211 Test Addr', 'Test2', NULL), ('456456', '123123', '311 Test Addr', 'Test3', NULL), ('456456', '123123', '411 Test Addr', 'Test4', NULL)`)
Expand Down Expand Up @@ -481,25 +481,25 @@ func (me *datasetTest) TestPreparedInsertDefaultValues() {
func (me *datasetTest) TestPreparedInsertSqlWithEmbeddedStruct() {
t := me.T()
ds1 := From("items")
type phone struct {
type Phone struct {
Primary string `db:"primary_phone"`
Home string `db:"home_phone"`
}
type item struct {
phone
Phone
Address string `db:"address"`
Name string `db:"name"`
}
sql, args, err := ds1.Prepared(true).ToInsertSql(item{Name: "Test", Address: "111 Test Addr", phone: phone{Home: "123123", Primary: "456456"}})
sql, args, err := ds1.Prepared(true).ToInsertSql(item{Name: "Test", Address: "111 Test Addr", Phone: Phone{Home: "123123", Primary: "456456"}})
assert.NoError(t, err)
assert.Equal(t, args, []interface{}{"456456", "123123", "111 Test Addr", "Test"})
assert.Equal(t, sql, `INSERT INTO "items" ("primary_phone", "home_phone", "address", "name") VALUES (?, ?, ?, ?)`)

sql, args, err = ds1.Prepared(true).ToInsertSql(
item{Address: "111 Test Addr", Name: "Test1", phone: phone{Home: "123123", Primary: "456456"}},
item{Address: "211 Test Addr", Name: "Test2", phone: phone{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", phone: phone{Home: "123123", Primary: "456456"}},
item{Address: "411 Test Addr", Name: "Test4", phone: phone{Home: "123123", Primary: "456456"}},
item{Address: "111 Test Addr", Name: "Test1", Phone: Phone{Home: "123123", Primary: "456456"}},
item{Address: "211 Test Addr", Name: "Test2", Phone: Phone{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", Phone: Phone{Home: "123123", Primary: "456456"}},
item{Address: "411 Test Addr", Name: "Test4", Phone: Phone{Home: "123123", Primary: "456456"}},
)
assert.NoError(t, err)
assert.Equal(t, args, []interface{}{
Expand All @@ -514,25 +514,25 @@ func (me *datasetTest) TestPreparedInsertSqlWithEmbeddedStruct() {
func (me *datasetTest) TestPreparedInsertSqlWithEmbeddedStructPtr() {
t := me.T()
ds1 := From("items")
type phone struct {
type Phone struct {
Primary string `db:"primary_phone"`
Home string `db:"home_phone"`
}
type item struct {
*phone
*Phone
Address string `db:"address"`
Name string `db:"name"`
}
sql, args, err := ds1.Prepared(true).ToInsertSql(item{Name: "Test", Address: "111 Test Addr", phone: &phone{Home: "123123", Primary: "456456"}})
sql, args, err := ds1.Prepared(true).ToInsertSql(item{Name: "Test", Address: "111 Test Addr", Phone: &Phone{Home: "123123", Primary: "456456"}})
assert.NoError(t, err)
assert.Equal(t, args, []interface{}{"456456", "123123", "111 Test Addr", "Test"})
assert.Equal(t, sql, `INSERT INTO "items" ("primary_phone", "home_phone", "address", "name") VALUES (?, ?, ?, ?)`)

sql, args, err = ds1.Prepared(true).ToInsertSql(
item{Address: "111 Test Addr", Name: "Test1", phone: &phone{Home: "123123", Primary: "456456"}},
item{Address: "211 Test Addr", Name: "Test2", phone: &phone{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", phone: &phone{Home: "123123", Primary: "456456"}},
item{Address: "411 Test Addr", Name: "Test4", phone: &phone{Home: "123123", Primary: "456456"}},
item{Address: "111 Test Addr", Name: "Test1", Phone: &Phone{Home: "123123", Primary: "456456"}},
item{Address: "211 Test Addr", Name: "Test2", Phone: &Phone{Home: "123123", Primary: "456456"}},
item{Address: "311 Test Addr", Name: "Test3", Phone: &Phone{Home: "123123", Primary: "456456"}},
item{Address: "411 Test Addr", Name: "Test4", Phone: &Phone{Home: "123123", Primary: "456456"}},
)
assert.NoError(t, err)
assert.Equal(t, args, []interface{}{
Expand Down
20 changes: 10 additions & 10 deletions dataset_select_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,22 @@ func (me *datasetTest) TestSelect() {
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT DISTINCT("a") AS "distinct", COUNT("a") AS "count", CASE WHEN (MIN("a") = 10) THEN TRUE ELSE FALSE END, CASE WHEN (AVG("a") != 10) THEN TRUE ELSE FALSE END, CASE WHEN (FIRST("a") > 10) THEN TRUE ELSE FALSE END, CASE WHEN (FIRST("a") >= 10) THEN TRUE ELSE FALSE END, CASE WHEN (LAST("a") < 10) THEN TRUE ELSE FALSE END, CASE WHEN (LAST("a") <= 10) THEN TRUE ELSE FALSE END, SUM("a") AS "sum", COALESCE("a", 'a') AS "colaseced"`)

type myStruct struct {
type MyStruct struct {
Name string
Address string `db:"address"`
EmailAddress string `db:"email_address"`
FakeCol string `db:"-"`
}
sql, _, err = ds1.Select(&myStruct{}).ToSql()
sql, _, err = ds1.Select(&MyStruct{}).ToSql()
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT "address", "email_address", "name" FROM "test"`)

sql, _, err = ds1.Select(myStruct{}).ToSql()
sql, _, err = ds1.Select(MyStruct{}).ToSql()
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT "address", "email_address", "name" FROM "test"`)

type myStruct2 struct {
myStruct
MyStruct
Zipcode string `db:"zipcode"`
}

Expand All @@ -83,7 +83,7 @@ func (me *datasetTest) TestSelect() {
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT "address", "email_address", "name", "zipcode" FROM "test"`)

var myStructs []myStruct
var myStructs []MyStruct
sql, _, err = ds1.Select(&myStructs).ToSql()
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT "address", "email_address", "name" FROM "test"`)
Expand Down Expand Up @@ -122,22 +122,22 @@ func (me *datasetTest) TestSelectDistinct() {
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT DISTINCT "id" AS "other_id", COUNT(*) AS "count" FROM "test"`)

type myStruct struct {
type MyStruct struct {
Name string
Address string `db:"address"`
EmailAddress string `db:"email_address"`
FakeCol string `db:"-"`
}
sql, _, err = ds1.SelectDistinct(&myStruct{}).ToSql()
sql, _, err = ds1.SelectDistinct(&MyStruct{}).ToSql()
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT DISTINCT "address", "email_address", "name" FROM "test"`)

sql, _, err = ds1.SelectDistinct(myStruct{}).ToSql()
sql, _, err = ds1.SelectDistinct(MyStruct{}).ToSql()
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT DISTINCT "address", "email_address", "name" FROM "test"`)

type myStruct2 struct {
myStruct
MyStruct
Zipcode string `db:"zipcode"`
}

Expand All @@ -149,7 +149,7 @@ func (me *datasetTest) TestSelectDistinct() {
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT DISTINCT "address", "email_address", "name", "zipcode" FROM "test"`)

var myStructs []myStruct
var myStructs []MyStruct
sql, _, err = ds1.SelectDistinct(&myStructs).ToSql()
assert.NoError(t, err)
assert.Equal(t, sql, `SELECT DISTINCT "address", "email_address", "name" FROM "test"`)
Expand Down
Loading

0 comments on commit a96f4ed

Please sign in to comment.