diff options
| author | Nigel Tao <nigeltao@golang.org> | 2013-08-16 11:23:35 +1000 |
|---|---|---|
| committer | Nigel Tao <nigeltao@golang.org> | 2013-08-16 11:23:35 +1000 |
| commit | bc2126507472e51a6820aecce9f07df6e4231a0a (patch) | |
| tree | 0c65c6b78f4535982724f8134d8107fd8153dd60 /src/pkg/database/sql/sql.go | |
| parent | b75a08d03c3d0fc659191dbc7eed174d5cb6f6c3 (diff) | |
| download | go-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.go | 22 |
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 |
