1
0
mirror of https://github.com/golang/go synced 2024-11-26 21:21:34 -07:00

database/sql: check for nil Scan pointers

Return nice errors and don't panic.

Fixes #4859

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/7383046
This commit is contained in:
Brad Fitzpatrick 2013-02-21 10:43:00 -08:00
parent 5833c96b0a
commit bca3f5fca0
2 changed files with 36 additions and 1 deletions

View File

@ -14,6 +14,8 @@ import (
"strconv"
)
var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
// driverArgs converts arguments from callers of Stmt.Exec and
// Stmt.Query into driver Values.
//
@ -75,34 +77,52 @@ func driverArgs(si driver.Stmt, args []interface{}) ([]driver.Value, error) {
// An error is returned if the copy would result in loss of information.
// dest should be a pointer type.
func convertAssign(dest, src interface{}) error {
// Common cases, without reflect. Fall through.
// Common cases, without reflect.
switch s := src.(type) {
case string:
switch d := dest.(type) {
case *string:
if d == nil {
return errNilPtr
}
*d = s
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = []byte(s)
return nil
}
case []byte:
switch d := dest.(type) {
case *string:
if d == nil {
return errNilPtr
}
*d = string(s)
return nil
case *interface{}:
if d == nil {
return errNilPtr
}
bcopy := make([]byte, len(s))
copy(bcopy, s)
*d = bcopy
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = s
return nil
}
case nil:
switch d := dest.(type) {
case *[]byte:
if d == nil {
return errNilPtr
}
*d = nil
return nil
}
@ -140,6 +160,9 @@ func convertAssign(dest, src interface{}) error {
if dpv.Kind() != reflect.Ptr {
return errors.New("destination not a pointer")
}
if dpv.IsNil() {
return errNilPtr
}
if !sv.IsValid() {
sv = reflect.ValueOf(src)

View File

@ -696,3 +696,15 @@ func nullTestRun(t *testing.T, spec nullTestSpec) {
}
}
}
// golang.org/issue/4859
func TestQueryRowNilScanDest(t *testing.T) {
db := newTestDB(t, "people")
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"
if err == nil || err.Error() != want {
t.Errorf("error = %q; want %q", err.Error(), want)
}
}