]> Cypherpunks repositories - gostls13.git/commitdiff
database/sql: include SQL column name in Scan() error message
authorHaraldNordgren <haraldnordgren@gmail.com>
Sun, 7 Jan 2018 14:08:59 +0000 (15:08 +0100)
committerDaniel Theophanes <kardianos@gmail.com>
Tue, 13 Feb 2018 21:24:53 +0000 (21:24 +0000)
When 'convertAssign' gives an error, instead of giving just the index of
the failing column -- which is not always helpful, especially when there
are lots of columns in the query -- utilize 'rs.rowsi.Columns()' to
extract the underlying column name and include that in the error string:

    sql: Scan error on column index 0, name "some_column": ...

Fixes #23362

Change-Id: I0fe71ff3c25f4c0dd9fc6aa2c2da2360dd93e3e0
Reviewed-on: https://go-review.googlesource.com/86537
Reviewed-by: Harald Nordgren <haraldnordgren@gmail.com>
Reviewed-by: Daniel Theophanes <kardianos@gmail.com>
Run-TryBot: Daniel Theophanes <kardianos@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/database/sql/sql.go
src/database/sql/sql_test.go

index 8f5588ed2680886be6766e68d0feb8b77e5d9e29..a6fa153d94795486a59e5a957ad7bb285c2f3d2d 100644 (file)
@@ -2885,7 +2885,7 @@ func (rs *Rows) Scan(dest ...interface{}) error {
        for i, sv := range rs.lastcols {
                err := convertAssign(dest[i], sv)
                if err != nil {
-                       return fmt.Errorf("sql: Scan error on column index %d: %v", i, err)
+                       return fmt.Errorf(`sql: Scan error on column index %d, name %q: %v`, i, rs.rowsi.Columns()[i], err)
                }
        }
        return nil
index ae6bf7102e36c907fdd293ffee615ff6fb5c8f0f..405e818185821ac6f115f3cd8eb24c2fb3f76712 100644 (file)
@@ -1338,6 +1338,57 @@ func TestConnQuery(t *testing.T) {
        }
 }
 
+func TestInvalidNilValues(t *testing.T) {
+       var date1 time.Time
+       var date2 int
+
+       tests := []struct {
+               name          string
+               input         interface{}
+               expectedError string
+       }{
+               {
+                       name:          "time.Time",
+                       input:         &date1,
+                       expectedError: `sql: Scan error on column index 0, name "bdate": unsupported Scan, storing driver.Value type <nil> into type *time.Time`,
+               },
+               {
+                       name:          "int",
+                       input:         &date2,
+                       expectedError: `sql: Scan error on column index 0, name "bdate": converting driver.Value type <nil> ("<nil>") to a int: invalid syntax`,
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       db := newTestDB(t, "people")
+                       defer closeDB(t, db)
+
+                       ctx, cancel := context.WithCancel(context.Background())
+                       defer cancel()
+                       conn, err := db.Conn(ctx)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+                       conn.dc.ci.(*fakeConn).skipDirtySession = true
+                       defer conn.Close()
+
+                       err = conn.QueryRowContext(ctx, "SELECT|people|bdate|age=?", 1).Scan(tt.input)
+                       if err == nil {
+                               t.Fatal("expected error when querying nil column, but suceeded")
+                       }
+                       if err.Error() != tt.expectedError {
+                               t.Fatalf("Expected error: %s\nReceived: %s", tt.expectedError, err.Error())
+                       }
+
+                       err = conn.PingContext(ctx)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+               })
+       }
+}
+
 func TestConnTx(t *testing.T) {
        db := newTestDB(t, "people")
        defer closeDB(t, db)
@@ -1659,7 +1710,7 @@ func TestQueryRowNilScanDest(t *testing.T) {
        defer closeDB(t, db)
        var name *string // nil pointer
        err := db.QueryRow("SELECT|people|name|").Scan(name)
-       want := "sql: Scan error on column index 0: destination pointer is nil"
+       want := `sql: Scan error on column index 0, name "name": destination pointer is nil`
        if err == nil || err.Error() != want {
                t.Errorf("error = %q; want %q", err.Error(), want)
        }