]> Cypherpunks repositories - gostls13.git/commitdiff
database/sql: prefer to return Rows.lasterr rather then a static error
authorDaniel Theophanes <kardianos@gmail.com>
Sat, 27 Oct 2018 21:12:52 +0000 (14:12 -0700)
committerDaniel Theophanes <kardianos@gmail.com>
Mon, 29 Oct 2018 16:11:22 +0000 (16:11 +0000)
Fixes #25829

Change-Id: I400fdaf0ef3a23bc0d61c4873ffa298e0cf0fc6a
Reviewed-on: https://go-review.googlesource.com/c/145204
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/database/sql/sql.go

index 1ffe252ee3a4004b1eccd7c61342aae66fa935e4..31db7a47d6d7b5ce8bab94e23a48f7fef1d02766 100644 (file)
@@ -2605,6 +2605,15 @@ type Rows struct {
        lastcols []driver.Value
 }
 
+// lasterrOrErrLocked returns either lasterr or the provided err.
+// rs.closemu must be read-locked.
+func (rs *Rows) lasterrOrErrLocked(err error) error {
+       if rs.lasterr != nil && rs.lasterr != io.EOF {
+               return rs.lasterr
+       }
+       return err
+}
+
 func (rs *Rows) initContextClose(ctx, txctx context.Context) {
        if ctx.Done() == nil && (txctx == nil || txctx.Done() == nil) {
                return
@@ -2728,22 +2737,22 @@ func (rs *Rows) NextResultSet() bool {
 func (rs *Rows) Err() error {
        rs.closemu.RLock()
        defer rs.closemu.RUnlock()
-       if rs.lasterr == io.EOF {
-               return nil
-       }
-       return rs.lasterr
+       return rs.lasterrOrErrLocked(nil)
 }
 
+var errRowsClosed = errors.New("sql: Rows are closed")
+var errNoRows = errors.New("sql: no Rows available")
+
 // Columns returns the column names.
 // Columns returns an error if the rows are closed.
 func (rs *Rows) Columns() ([]string, error) {
        rs.closemu.RLock()
        defer rs.closemu.RUnlock()
        if rs.closed {
-               return nil, errors.New("sql: Rows are closed")
+               return nil, rs.lasterrOrErrLocked(errRowsClosed)
        }
        if rs.rowsi == nil {
-               return nil, errors.New("sql: no Rows available")
+               return nil, rs.lasterrOrErrLocked(errNoRows)
        }
        rs.dc.Lock()
        defer rs.dc.Unlock()
@@ -2757,10 +2766,10 @@ func (rs *Rows) ColumnTypes() ([]*ColumnType, error) {
        rs.closemu.RLock()
        defer rs.closemu.RUnlock()
        if rs.closed {
-               return nil, errors.New("sql: Rows are closed")
+               return nil, rs.lasterrOrErrLocked(errRowsClosed)
        }
        if rs.rowsi == nil {
-               return nil, errors.New("sql: no Rows available")
+               return nil, rs.lasterrOrErrLocked(errNoRows)
        }
        rs.dc.Lock()
        defer rs.dc.Unlock()
@@ -2916,8 +2925,9 @@ func (rs *Rows) Scan(dest ...interface{}) error {
                return rs.lasterr
        }
        if rs.closed {
+               err := rs.lasterrOrErrLocked(errRowsClosed)
                rs.closemu.RUnlock()
-               return errors.New("sql: Rows are closed")
+               return err
        }
        rs.closemu.RUnlock()