Skip to content

Commit a817d1d

Browse files
committed
Invalidate cache on Rows.NextResultSet call
When reading multiple result sets from sqlx.Rows using StructScan, some information obtained usCCCing costly reflect operations is cached for performance optimisation. However, different result sets in a single sqlx.Rows object might have different structures, so cache should be invalidated and rebuild after each NextResultSet call. Now this method is not overwritten, so old cache interferes with new structures after first result set scan. Relates #857
1 parent 28212d4 commit a817d1d

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

sqlx.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"database/sql/driver"
66
"errors"
77
"fmt"
8-
98
"io/ioutil"
109
"path/filepath"
1110
"reflect"
@@ -51,9 +50,9 @@ func mapper() *reflectx.Mapper {
5150

5251
// isScannable takes the reflect.Type and the actual dest value and returns
5352
// whether or not it's Scannable. Something is scannable if:
54-
// * it is not a struct
55-
// * it implements sql.Scanner
56-
// * it has no exported fields
53+
// - it is not a struct
54+
// - it implements sql.Scanner
55+
// - it has no exported fields
5756
func isScannable(t reflect.Type) bool {
5857
if reflect.PtrTo(t).Implements(_scannerInterface) {
5958
return true
@@ -633,6 +632,17 @@ func (r *Rows) StructScan(dest interface{}) error {
633632
return r.Err()
634633
}
635634

635+
// NextResultSet behaves like sql.NextResultSet, but cleans cache of previous result set.
636+
func (r *Rows) NextResultSet() bool {
637+
if !r.Rows.NextResultSet() {
638+
return false
639+
}
640+
r.started = false
641+
r.fields = nil
642+
r.values = nil
643+
return true
644+
}
645+
636646
// Connect to a database and verify with a ping.
637647
func Connect(driverName, dataSourceName string) (*DB, error) {
638648
db, err := Open(driverName, dataSourceName)
@@ -884,9 +894,9 @@ func structOnlyError(t reflect.Type) error {
884894
// then each row must only have one column which can scan into that type. This
885895
// allows you to do something like:
886896
//
887-
// rows, _ := db.Query("select id from people;")
888-
// var ids []int
889-
// scanAll(rows, &ids, false)
897+
// rows, _ := db.Query("select id from people;")
898+
// var ids []int
899+
// scanAll(rows, &ids, false)
890900
//
891901
// and ids will be a list of the id results. I realize that this is a desirable
892902
// interface to expose to users, but for now it will only be exposed via changes

0 commit comments

Comments
 (0)