database/sql: Check errors in QueryRow.Scan

The previous coding did not correctly check for errors from the driver's
Next() or Close(), which could mask genuine errors from the database, as
witnessed in issue #6651.

Even after this change errors from Close() will be ignored if the query
returned no rows (as Rows.Next will have closed the handle already), but it
is a lot easier for the drivers to guard against that.

Fixes #6651.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/41590043
This commit is contained in:
Marko Tiikkaja 2013-12-16 12:48:35 -08:00 committed by Brad Fitzpatrick
parent 54f39c997b
commit 1f20ab1116
3 changed files with 48 additions and 4 deletions

View file

@ -660,6 +660,35 @@ func TestQueryRowClosingStmt(t *testing.T) {
}
}
// Test issue 6651
func TestIssue6651(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
var v string
want := "error in rows.Next"
rowsCursorNextHook = func(dest []driver.Value) error {
return fmt.Errorf(want)
}
defer func() { rowsCursorNextHook = nil }()
err := db.QueryRow("SELECT|people|name|").Scan(&v)
if err == nil || err.Error() != want {
t.Errorf("error = %q; want %q", err, want)
}
rowsCursorNextHook = nil
want = "error in rows.Close"
rowsCloseHook = func(rows *Rows, err *error) {
*err = fmt.Errorf(want)
}
defer func() { rowsCloseHook = nil }()
err = db.QueryRow("SELECT|people|name|").Scan(&v)
if err == nil || err.Error() != want {
t.Errorf("error = %q; want %q", err, want)
}
}
type nullTestRow struct {
nullParam interface{}
notNullParam interface{}