aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/database/sql/sql.go
diff options
context:
space:
mode:
authorNigel Tao <nigeltao@golang.org>2013-08-16 11:23:35 +1000
committerNigel Tao <nigeltao@golang.org>2013-08-16 11:23:35 +1000
commitbc2126507472e51a6820aecce9f07df6e4231a0a (patch)
tree0c65c6b78f4535982724f8134d8107fd8153dd60 /src/pkg/database/sql/sql.go
parentb75a08d03c3d0fc659191dbc7eed174d5cb6f6c3 (diff)
downloadgo-bc2126507472e51a6820aecce9f07df6e4231a0a.tar.xz
database/sql: make Rows.Next returning false always implicitly call
Rows.Close. Previously, callers that followed the example code (but not call rows.Close after "for rows.Next() { ... }") could leak statements if the driver returned an error other than io.EOF. R=bradfitz, alex.brainman CC=golang-dev, rsc https://golang.org/cl/12677050
Diffstat (limited to 'src/pkg/database/sql/sql.go')
-rw-r--r--src/pkg/database/sql/sql.go22
1 files changed, 9 insertions, 13 deletions
diff --git a/src/pkg/database/sql/sql.go b/src/pkg/database/sql/sql.go
index f0c86a8aeb..d81f6fe984 100644
--- a/src/pkg/database/sql/sql.go
+++ b/src/pkg/database/sql/sql.go
@@ -1293,7 +1293,7 @@ type Rows struct {
closed bool
lastcols []driver.Value
- lasterr error
+ lasterr error // non-nil only if closed is true
closeStmt driver.Stmt // if non-nil, statement to Close on close
}
@@ -1305,20 +1305,19 @@ func (rs *Rows) Next() bool {
if rs.closed {
return false
}
- if rs.lasterr != nil {
- return false
- }
if rs.lastcols == nil {
rs.lastcols = make([]driver.Value, len(rs.rowsi.Columns()))
}
rs.lasterr = rs.rowsi.Next(rs.lastcols)
- if rs.lasterr == io.EOF {
+ if rs.lasterr != nil {
rs.Close()
+ return false
}
- return rs.lasterr == nil
+ return true
}
// Err returns the error, if any, that was encountered during iteration.
+// Err may be called after an explicit or implicit Close.
func (rs *Rows) Err() error {
if rs.lasterr == io.EOF {
return nil
@@ -1353,10 +1352,7 @@ func (rs *Rows) Columns() ([]string, error) {
// is of type []byte, a copy is made and the caller owns the result.
func (rs *Rows) Scan(dest ...interface{}) error {
if rs.closed {
- return errors.New("sql: Rows closed")
- }
- if rs.lasterr != nil {
- return rs.lasterr
+ return errors.New("sql: Rows are closed")
}
if rs.lastcols == nil {
return errors.New("sql: Scan called without calling Next")
@@ -1375,9 +1371,9 @@ func (rs *Rows) Scan(dest ...interface{}) error {
var rowsCloseHook func(*Rows, *error)
-// Close closes the Rows, preventing further enumeration. If the
-// end is encountered, the Rows are closed automatically. Close
-// is idempotent.
+// Close closes the Rows, preventing further enumeration. If Next returns
+// false, the Rows are closed automatically and it will suffice to check the
+// result of Err. Close is idempotent and does not affect the result of Err.
func (rs *Rows) Close() error {
if rs.closed {
return nil