From 421d1cdb91272811eee9c2cdcdf4ff4b40568ef8 Mon Sep 17 00:00:00 2001 From: GaYoung Park Date: Tue, 10 Aug 2021 13:59:26 -0700 Subject: [PATCH] Make Select reset slice length --- sqlx.go | 8 +++++--- sqlx_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/sqlx.go b/sqlx.go index 112ef70e..f7b28768 100644 --- a/sqlx.go +++ b/sqlx.go @@ -878,9 +878,10 @@ func structOnlyError(t reflect.Type) error { } // scanAll scans all rows into a destination, which must be a slice of any -// type. If the destination slice type is a Struct, then StructScan will be -// used on each row. If the destination is some other kind of base type, then -// each row must only have one column which can scan into that type. This +// type. It resets the slice length to zero before appending each element to +// the slice. If the destination slice type is a Struct, then StructScan will +// be used on each row. If the destination is some other kind of base type, +// then each row must only have one column which can scan into that type. This // allows you to do something like: // // rows, _ := db.Query("select id from people;") @@ -910,6 +911,7 @@ func scanAll(rows rowsi, dest interface{}, structOnly bool) error { if err != nil { return err } + direct.SetLen(0) isPtr := slice.Elem().Kind() == reflect.Ptr base := reflectx.Deref(slice.Elem()) diff --git a/sqlx_test.go b/sqlx_test.go index a51528ea..1d4aa20d 100644 --- a/sqlx_test.go +++ b/sqlx_test.go @@ -1892,3 +1892,35 @@ func TestIn130Regression(t *testing.T) { } }) } + +func TestSelectReset(t *testing.T) { + RunWithSchema(defaultSchema, t, func(db *DB, t *testing.T, now string) { + loadDefaultFixture(db, t) + + filledDest := []string{"a", "b", "c"} + err := db.Select(&filledDest, "SELECT first_name FROM person ORDER BY first_name ASC;") + if err != nil { + t.Fatal(err) + } + if len(filledDest) != 2 { + t.Errorf("Expected 2 first names, got %d.", len(filledDest)) + } + expected := []string{"Jason", "John"} + for i, got := range filledDest { + if got != expected[i] { + t.Errorf("Expected %d result to be %s, but got %s.", i, expected[i], got) + } + } + + var emptyDest []string + err = db.Select(&emptyDest, "SELECT first_name FROM person WHERE first_name = 'Jack';") + if err != nil { + t.Fatal(err) + } + // Verify that selecting 0 rows into a nil target didn't create a + // non-nil slice. + if emptyDest != nil { + t.Error("Expected emptyDest to be nil") + } + }) +}