From 39ce30679a2033ebd3afcd33130dc6e655b295a0 Mon Sep 17 00:00:00 2001 From: Doug Martin Date: Wed, 27 May 2015 10:33:37 -0400 Subject: [PATCH] v2.0.1 * Fixed issue when `ScanStruct(s)` was used with `SelectDistinct` and caused a panic. --- HISTORY.md | 4 ++++ dataset_actions_test.go | 24 +++++++++++++++++++++++ dataset_select.go | 10 ++++++---- dataset_select_test.go | 42 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 5 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 66043a76..11be80d9 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,7 @@ +## v2.0.1 + +* Fixed issue when `ScanStruct(s)` was used with `SelectDistinct` and caused a panic. + ## v2.0.0 * When scanning a struct or slice of structs, the struct(s) will be parsed for the column names to select. [#9](https://github.com/doug-martin/goqu/pull/9) - [@technotronicoz](https://github.com/TechnotronicOz) diff --git a/dataset_actions_test.go b/dataset_actions_test.go index 69aa79c1..87966842 100644 --- a/dataset_actions_test.go +++ b/dataset_actions_test.go @@ -18,6 +18,10 @@ func (me *datasetTest) TestScanStructs() { WithArgs(). WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).FromCSVString("111 Test Addr,Test1\n211 Test Addr,Test2")) + sqlmock.ExpectQuery(`SELECT DISTINCT "name" FROM "items"`). + WithArgs(). + WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).FromCSVString("111 Test Addr,Test1\n211 Test Addr,Test2")) + sqlmock.ExpectQuery(`SELECT "test" FROM "items"`). WithArgs(). WillReturnRows(sqlmock.NewRows([]string{"test"}).FromCSVString("test1\ntest2")) @@ -32,6 +36,15 @@ func (me *datasetTest) TestScanStructs() { assert.Equal(t, items[1].Address, "211 Test Addr") assert.Equal(t, items[1].Name, "Test2") + items = items[0:0] + assert.NoError(t, db.From("items").SelectDistinct("name").ScanStructs(&items)) + assert.Len(t, items, 2) + assert.Equal(t, items[0].Address, "111 Test Addr") + assert.Equal(t, items[0].Name, "Test1") + + assert.Equal(t, items[1].Address, "211 Test Addr") + assert.Equal(t, items[1].Name, "Test2") + items = items[0:0] assert.EqualError(t, db.From("items").ScanStructs(items), "goqu: Type must be a pointer to a slice when calling ScanStructs") assert.EqualError(t, db.From("items").ScanStructs(&dsTestActionItem{}), "goqu: Type must be a pointer to a slice when calling ScanStructs") @@ -78,6 +91,10 @@ func (me *datasetTest) TestScanStruct() { WithArgs(). WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).FromCSVString("111 Test Addr,Test1")) + sqlmock.ExpectQuery(`SELECT DISTINCT "name" FROM "items" LIMIT 1`). + WithArgs(). + WillReturnRows(sqlmock.NewRows([]string{"address", "name"}).FromCSVString("111 Test Addr,Test1")) + sqlmock.ExpectQuery(`SELECT "test" FROM "items" LIMIT 1`). WithArgs(). WillReturnRows(sqlmock.NewRows([]string{"test"}).FromCSVString("test1\ntest2")) @@ -90,6 +107,13 @@ func (me *datasetTest) TestScanStruct() { assert.Equal(t, item.Address, "111 Test Addr") assert.Equal(t, item.Name, "Test1") + item = dsTestActionItem{} + found, err = db.From("items").SelectDistinct("name").ScanStruct(&item) + assert.NoError(t, err) + assert.True(t, found) + assert.Equal(t, item.Address, "111 Test Addr") + assert.Equal(t, item.Name, "Test1") + _, err = db.From("items").ScanStruct(item) assert.EqualError(t, err, "goqu: Type must be a pointer to a struct when calling ScanStruct") _, err = db.From("items").ScanStruct([]dsTestActionItem{}) diff --git a/dataset_select.go b/dataset_select.go index 782dbd53..329f58af 100644 --- a/dataset_select.go +++ b/dataset_select.go @@ -55,10 +55,12 @@ func (me *Dataset) ClearSelect() *Dataset { //Returns true if using default SELECT * func (me *Dataset) isDefaultSelect() bool { ret := false - selects := me.clauses.Select.Columns() - if len(selects) == 1 { - if l, ok := selects[0].(LiteralExpression); ok && l.Literal() == "*" { - ret = true + if me.clauses.Select != nil { + selects := me.clauses.Select.Columns() + if len(selects) == 1 { + if l, ok := selects[0].(LiteralExpression); ok && l.Literal() == "*" { + ret = true + } } } return ret diff --git a/dataset_select_test.go b/dataset_select_test.go index c8214e01..4754ea43 100644 --- a/dataset_select_test.go +++ b/dataset_select_test.go @@ -97,7 +97,7 @@ func (me *datasetTest) TestSelect() { assert.Equal(t, sql, `SELECT * FROM "test"`) } -func (me *datasetTest) TestDistinctSelect() { +func (me *datasetTest) TestSelectDistinct() { t := me.T() ds1 := From("test") @@ -121,6 +121,46 @@ func (me *datasetTest) TestDistinctSelect() { assert.NoError(t, err) assert.Equal(t, sql, `SELECT DISTINCT "id" AS "other_id", COUNT(*) AS "count" FROM "test"`) + type myStruct struct { + Name string + Address string `db:"address"` + EmailAddress string `db:"email_address"` + } + 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() + assert.NoError(t, err) + assert.Equal(t, sql, `SELECT DISTINCT "address", "email_address", "name" FROM "test"`) + + type myStruct2 struct { + myStruct + Zipcode string `db:"zipcode"` + } + + sql, _, err = ds1.SelectDistinct(&myStruct2{}).ToSql() + assert.NoError(t, err) + assert.Equal(t, sql, `SELECT DISTINCT "address", "email_address", "name", "zipcode" FROM "test"`) + + sql, _, err = ds1.SelectDistinct(myStruct2{}).ToSql() + assert.NoError(t, err) + assert.Equal(t, sql, `SELECT DISTINCT "address", "email_address", "name", "zipcode" FROM "test"`) + + 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"`) + + sql, _, err = ds1.SelectDistinct(myStructs).ToSql() + assert.NoError(t, err) + assert.Equal(t, sql, `SELECT DISTINCT "address", "email_address", "name" FROM "test"`) + + //should not change original + sql, _, err = ds1.ToSql() + assert.NoError(t, err) + assert.Equal(t, sql, `SELECT * FROM "test"`) + //should not change original sql, _, err = ds1.ToSql() assert.NoError(t, err)