diff options
Diffstat (limited to 'src/pkg/database/sql/convert.go')
| -rw-r--r-- | src/pkg/database/sql/convert.go | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/src/pkg/database/sql/convert.go b/src/pkg/database/sql/convert.go index bfcb03ccf8..964dc18485 100644 --- a/src/pkg/database/sql/convert.go +++ b/src/pkg/database/sql/convert.go @@ -14,19 +14,61 @@ import ( "strconv" ) -// subsetTypeArgs takes a slice of arguments from callers of the sql -// package and converts them into a slice of the driver package's -// "subset types". -func subsetTypeArgs(args []interface{}) ([]driver.Value, error) { - out := make([]driver.Value, len(args)) +// driverArgs converts arguments from callers of Stmt.Exec and +// Stmt.Query into driver Values. +// +// The statement si may be nil, if no statement is available. +func driverArgs(si driver.Stmt, args []interface{}) ([]driver.Value, error) { + dargs := make([]driver.Value, len(args)) + cc, ok := si.(driver.ColumnConverter) + + // Normal path, for a driver.Stmt that is not a ColumnConverter. + if !ok { + for n, arg := range args { + var err error + dargs[n], err = driver.DefaultParameterConverter.ConvertValue(arg) + if err != nil { + return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err) + } + } + return dargs, nil + } + + // Let the Stmt convert its own arguments. for n, arg := range args { + // First, see if the value itself knows how to convert + // itself to a driver type. For example, a NullString + // struct changing into a string or nil. + if svi, ok := arg.(driver.Valuer); ok { + sv, err := svi.Value() + if err != nil { + return nil, fmt.Errorf("sql: argument index %d from Value: %v", n, err) + } + if !driver.IsValue(sv) { + return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from Value", n, sv) + } + arg = sv + } + + // Second, ask the column to sanity check itself. For + // example, drivers might use this to make sure that + // an int64 values being inserted into a 16-bit + // integer field is in range (before getting + // truncated), or that a nil can't go into a NOT NULL + // column before going across the network to get the + // same error. var err error - out[n], err = driver.DefaultParameterConverter.ConvertValue(arg) + dargs[n], err = cc.ColumnConverter(n).ConvertValue(arg) if err != nil { - return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n+1, err) + return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n, err) + } + if !driver.IsValue(dargs[n]) { + return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T", + arg, dargs[n]) } } - return out, nil + + return dargs, nil } // convertAssign copies to dest the value in src, converting it if possible. |
