Keyboard Shortcuts

File
u :up to issue
m :publish + mail comments
M :edit review message
j / k :jump to file after / before current file
J / K :jump to next file with a comment after / before current file
Side-by-side diff
i :toggle intra-line diffs
e :expand all comments
c :collapse all comments
s :toggle showing all comments
n / p :next / previous diff chunk or comment
N / P :next / previous comment
<Up> / <Down> :next / previous line
<Enter> :respond to / edit current comment
d :mark current comment as done
Issue
u :up to list of issues
m :publish + mail comments
j / k :jump to patch after / before current patch
o / <Enter> :open current patch in side-by-side view
i :open current patch in unified diff view
Issue List
j / k :jump to issue after / before current issue
o / <Enter> :open current issue
# : close issue
Comment/message editing
<Ctrl> + s or <Ctrl> + Enter :save comment
<Esc> :cancel edit
Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(80)
Issues Repositories Search
Open Issues | Closed Issues | All Issues | Sign in with your Google Account to create issues and add comments

Issue 41590043: code review 41590043: database/sql: Check errors in QueryRow.Scan

Can't Edit
Can't Publish+Mail
Start Review
Created:
12 years ago by johto
Modified:
12 years ago
Reviewers:
bradfitz
CC:
golang-dev, bradfitz
Visibility:
Public.
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 issue 6651.

Patch Set 1 #

Patch Set 2 : diff -r 3895ad0afefe https://code.google.com/p/go #

Patch Set 3 : diff -r 3895ad0afefe https://code.google.com/p/go #

Patch Set 4 : diff -r 24bc2c8febe3 https://code.google.com/p/go #

Created: 12 years ago
Download [raw] [tar.bz2]
Unified diffs Side-by-side diffs Delta from patch set Stats (+48 lines, -4 lines) Patch
M src/pkg/database/sql/fakedb_test.go View 1 2 3 1 chunk +6 lines, -0 lines 0 comments Download
M src/pkg/database/sql/sql.go View 1 2 chunks +13 lines, -4 lines 0 comments Download
M src/pkg/database/sql/sql_test.go View 1 2 3 1 chunk +29 lines, -0 lines 0 comments Download
Total messages: 6
|
johto
Hello golang-dev@googlegroups.com, I'd like you to review this change to https://code.google.com/p/go
12 years ago (2013年12月12日 23:33:41 UTC) #1
Hello golang-dev@googlegroups.com,
I'd like you to review this change to
https://code.google.com/p/go 
Sign in to reply to this message.
johto
On 12/13/13, 12:33 AM, I wrote: > Message: > Hello golang-dev@googlegroups.com, > > I'd like ...
12 years ago (2013年12月14日 01:10:07 UTC) #2
On 12/13/13, 12:33 AM, I wrote:
> Message:
> Hello golang-dev@googlegroups.com,
>
> I'd like you to review this change to
> https://code.google.com/p/go
Updated this CL to make the tests use a new hook instead. The previous 
approach was too ad-hoc, and extremely ugly.
.marko
Sign in to reply to this message.
bradfitz
Marko, You'll need to submit the CLA before for this to be accepted: http://golang.org/doc/contribute.html#copyright Please ...
12 years ago (2013年12月16日 20:28:42 UTC) #3
Marko,
You'll need to submit the CLA before for this to be accepted:
http://golang.org/doc/contribute.html#copyright
Please reply here when you've done so. Thanks!
On Thu, Dec 12, 2013 at 3:33 PM, <marko@joh.to> wrote:
> Reviewers: golang-dev1,
>
> Message:
> Hello golang-dev@googlegroups.com,
>
> I'd like you to review this change to
> https://code.google.com/p/go
>
>
> Description:
> 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 issue 6651.
>
> Please review this at https://codereview.appspot.com/41590043/
>
> Affected files (+65, -4 lines):
> M src/pkg/database/sql/fakedb_test.go
> M src/pkg/database/sql/sql.go
> M src/pkg/database/sql/sql_test.go
>
>
> Index: src/pkg/database/sql/fakedb_test.go
> ===================================================================
> --- a/src/pkg/database/sql/fakedb_test.go
> +++ b/src/pkg/database/sql/fakedb_test.go
> @@ -592,6 +592,12 @@
> time.Sleep(time.Duration(args[1].(int64))
> * time.Millisecond)
> }
> }
> + } else if s.table == "issue6651" {
> + if len(s.whereCol) != 1 || s.whereCol[0] !=
> "failonrowsnext" {
> + return nil, fmt.Errorf("fakedb: invalid where
> clause for table issue6651")
> + }
> + failonrowsnext := args[0].(bool)
> + return &issue6651Rows{failonrowsnext: failonrowsnext}, nil
> }
>
> t.mu.Lock()
> @@ -642,6 +648,26 @@
> return cursor, nil
> }
>
> +type issue6651Rows struct {
> + failonrowsnext bool
> +}
> +
> +func (r *issue6651Rows) Columns() []string {
> + return []string{"failure"}
> +}
> +
> +func (r *issue6651Rows) Next(dest []driver.Value) error {
> + if r.failonrowsnext {
> + return fmt.Errorf("error in rows.Next")
> + }
> + dest[0] = false
> + return nil
> +}
> +
> +func (r *issue6651Rows) Close() error {
> + return nil
> +}
> +
> func (s *fakeStmt) NumInput() int {
> return s.placeholders
> }
> Index: src/pkg/database/sql/sql.go
> ===================================================================
> --- a/src/pkg/database/sql/sql.go
> +++ b/src/pkg/database/sql/sql.go
> @@ -1495,10 +1495,12 @@
> closeStmt driver.Stmt // if non-nil, statement to Close on close
> }
>
> -// Next prepares the next result row for reading with the Scan method.
> -// It returns true on success, false if there is no next result row.
> -// Every call to Scan, even the first one, must be preceded by a call
> -// to Next.
> +// Next prepares the next result row for reading with the Scan method. It
> +// returns true on success, or false if there is no next result row or an
> error
> +// happened while preparing it. Err should be consulted to distinguish
> between
> +// the two cases.
> +//
> +// Every call to Scan, even the first one, must be preceded by a call to
> Next.
> func (rs *Rows) Next() bool {
> if rs.closed {
> return false
> @@ -1625,12 +1627,19 @@
> }
>
> if !r.rows.Next() {
> + if err := r.rows.Err(); err != nil {
> + return err
> + }
> return ErrNoRows
> }
> err := r.rows.Scan(dest...)
> if err != nil {
> return err
> }
> + // Make sure the query can be processed to completion with no
> errors.
> + if err := r.rows.Close(); err != nil {
> + return err
> + }
>
> return nil
> }
> Index: src/pkg/database/sql/sql_test.go
> ===================================================================
> --- a/src/pkg/database/sql/sql_test.go
> +++ b/src/pkg/database/sql/sql_test.go
> @@ -58,6 +58,9 @@
> exec(t, db, "CREATE|magicquery|op=string,millis=int32")
> exec(t, db, "INSERT|magicquery|op=sleep,millis=10")
> }
> + if name == "issue6651" {
> + exec(t, db, "CREATE|issue6651|failonrowsnext=bool")
> + }
> return db
> }
>
> @@ -660,6 +663,29 @@
> }
> }
>
> +// Test issue 6651
> +func TestIssue6651(t *testing.T) {
> + db := newTestDB(t, "issue6651")
> + defer closeDB(t, db)
> +
> + var v bool
> + err := db.QueryRow("SELECT|issue6651|
> failonrowsnext|failonrowsnext=?", true).Scan(&v)
> + want := "error in rows.Next"
> + if err == nil || err.Error() != want {
> + t.Errorf("error = %q; want %q", err, want)
> + }
> +
> + want = "error in rows.Close"
> + rowsCloseHook = func(rows *Rows, err *error) {
> + *err = fmt.Errorf(want)
> + }
> + defer func() { rowsCloseHook = nil }()
> + err = db.QueryRow("SELECT|issue6651|failonrowsnext|failonrowsnext=?",
> false).Scan(&v)
> + if err == nil || err.Error() != want {
> + t.Errorf("error = %q; want %q", err, want)
> + }
> +}
> +
> type nullTestRow struct {
> nullParam interface{}
> notNullParam interface{}
>
>
> --
>
> ---You received this message because you are subscribed to the Google
> Groups "golang-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-dev+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
Sign in to reply to this message.
johto
Hi Brad, On 12/16/13, 9:28 PM, Brad Fitzpatrick wrote: > You'll need to submit the ...
12 years ago (2013年12月16日 20:32:15 UTC) #4
Hi Brad,
On 12/16/13, 9:28 PM, Brad Fitzpatrick wrote:
> You'll need to submit the CLA before for this to be accepted:
> http://golang.org/doc/contribute.html#copyright
>
> Please reply here when you've done so. Thanks!
I've submitted the online form just now.
.marko
Sign in to reply to this message.
bradfitz
LGTM On Thu, Dec 12, 2013 at 3:33 PM, <marko@joh.to> wrote: > Reviewers: golang-dev1, > ...
12 years ago (2013年12月16日 20:48:29 UTC) #5
LGTM
On Thu, Dec 12, 2013 at 3:33 PM, <marko@joh.to> wrote:
> Reviewers: golang-dev1,
>
> Message:
> Hello golang-dev@googlegroups.com,
>
> I'd like you to review this change to
> https://code.google.com/p/go
>
>
> Description:
> 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 issue 6651.
>
> Please review this at https://codereview.appspot.com/41590043/
>
> Affected files (+65, -4 lines):
> M src/pkg/database/sql/fakedb_test.go
> M src/pkg/database/sql/sql.go
> M src/pkg/database/sql/sql_test.go
>
>
> Index: src/pkg/database/sql/fakedb_test.go
> ===================================================================
> --- a/src/pkg/database/sql/fakedb_test.go
> +++ b/src/pkg/database/sql/fakedb_test.go
> @@ -592,6 +592,12 @@
> time.Sleep(time.Duration(args[1].(int64))
> * time.Millisecond)
> }
> }
> + } else if s.table == "issue6651" {
> + if len(s.whereCol) != 1 || s.whereCol[0] !=
> "failonrowsnext" {
> + return nil, fmt.Errorf("fakedb: invalid where
> clause for table issue6651")
> + }
> + failonrowsnext := args[0].(bool)
> + return &issue6651Rows{failonrowsnext: failonrowsnext}, nil
> }
>
> t.mu.Lock()
> @@ -642,6 +648,26 @@
> return cursor, nil
> }
>
> +type issue6651Rows struct {
> + failonrowsnext bool
> +}
> +
> +func (r *issue6651Rows) Columns() []string {
> + return []string{"failure"}
> +}
> +
> +func (r *issue6651Rows) Next(dest []driver.Value) error {
> + if r.failonrowsnext {
> + return fmt.Errorf("error in rows.Next")
> + }
> + dest[0] = false
> + return nil
> +}
> +
> +func (r *issue6651Rows) Close() error {
> + return nil
> +}
> +
> func (s *fakeStmt) NumInput() int {
> return s.placeholders
> }
> Index: src/pkg/database/sql/sql.go
> ===================================================================
> --- a/src/pkg/database/sql/sql.go
> +++ b/src/pkg/database/sql/sql.go
> @@ -1495,10 +1495,12 @@
> closeStmt driver.Stmt // if non-nil, statement to Close on close
> }
>
> -// Next prepares the next result row for reading with the Scan method.
> -// It returns true on success, false if there is no next result row.
> -// Every call to Scan, even the first one, must be preceded by a call
> -// to Next.
> +// Next prepares the next result row for reading with the Scan method. It
> +// returns true on success, or false if there is no next result row or an
> error
> +// happened while preparing it. Err should be consulted to distinguish
> between
> +// the two cases.
> +//
> +// Every call to Scan, even the first one, must be preceded by a call to
> Next.
> func (rs *Rows) Next() bool {
> if rs.closed {
> return false
> @@ -1625,12 +1627,19 @@
> }
>
> if !r.rows.Next() {
> + if err := r.rows.Err(); err != nil {
> + return err
> + }
> return ErrNoRows
> }
> err := r.rows.Scan(dest...)
> if err != nil {
> return err
> }
> + // Make sure the query can be processed to completion with no
> errors.
> + if err := r.rows.Close(); err != nil {
> + return err
> + }
>
> return nil
> }
> Index: src/pkg/database/sql/sql_test.go
> ===================================================================
> --- a/src/pkg/database/sql/sql_test.go
> +++ b/src/pkg/database/sql/sql_test.go
> @@ -58,6 +58,9 @@
> exec(t, db, "CREATE|magicquery|op=string,millis=int32")
> exec(t, db, "INSERT|magicquery|op=sleep,millis=10")
> }
> + if name == "issue6651" {
> + exec(t, db, "CREATE|issue6651|failonrowsnext=bool")
> + }
> return db
> }
>
> @@ -660,6 +663,29 @@
> }
> }
>
> +// Test issue 6651
> +func TestIssue6651(t *testing.T) {
> + db := newTestDB(t, "issue6651")
> + defer closeDB(t, db)
> +
> + var v bool
> + err := db.QueryRow("SELECT|issue6651|
> failonrowsnext|failonrowsnext=?", true).Scan(&v)
> + want := "error in rows.Next"
> + if err == nil || err.Error() != want {
> + t.Errorf("error = %q; want %q", err, want)
> + }
> +
> + want = "error in rows.Close"
> + rowsCloseHook = func(rows *Rows, err *error) {
> + *err = fmt.Errorf(want)
> + }
> + defer func() { rowsCloseHook = nil }()
> + err = db.QueryRow("SELECT|issue6651|failonrowsnext|failonrowsnext=?",
> false).Scan(&v)
> + if err == nil || err.Error() != want {
> + t.Errorf("error = %q; want %q", err, want)
> + }
> +}
> +
> type nullTestRow struct {
> nullParam interface{}
> notNullParam interface{}
>
>
> --
>
> ---You received this message because you are subscribed to the Google
> Groups "golang-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-dev+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
Sign in to reply to this message.
bradfitz
*** Submitted as https://code.google.com/p/go/source/detail?r=04f0931c9808 *** database/sql: Check errors in QueryRow.Scan The previous coding did not ...
12 years ago (2013年12月16日 20:48:42 UTC) #6
*** Submitted as https://code.google.com/p/go/source/detail?r=04f0931c9808 ***
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 issue 6651.
R=golang-dev, bradfitz
CC=golang-dev
https://codereview.appspot.com/41590043
Committer: Brad Fitzpatrick <bradfitz@golang.org>
Sign in to reply to this message.
|
Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b

AltStyle によって変換されたページ (->オリジナル) /