diff options
Diffstat (limited to 'src/pkg/database/sql/convert.go')
-rw-r--r-- | src/pkg/database/sql/convert.go | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/src/pkg/database/sql/convert.go b/src/pkg/database/sql/convert.go index 853a7826c..c04adde1f 100644 --- a/src/pkg/database/sql/convert.go +++ b/src/pkg/database/sql/convert.go @@ -19,9 +19,13 @@ var errNilPtr = errors.New("destination pointer is nil") // embedded in descript // 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) { +// The statement ds may be nil, if no statement is available. +func driverArgs(ds *driverStmt, args []interface{}) ([]driver.Value, error) { dargs := make([]driver.Value, len(args)) + var si driver.Stmt + if ds != nil { + si = ds.si + } cc, ok := si.(driver.ColumnConverter) // Normal path, for a driver.Stmt that is not a ColumnConverter. @@ -60,7 +64,9 @@ func driverArgs(si driver.Stmt, args []interface{}) ([]driver.Value, error) { // column before going across the network to get the // same error. var err error + ds.Lock() dargs[n], err = cc.ColumnConverter(n).ConvertValue(arg) + ds.Unlock() if err != nil { return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n, err) } @@ -106,25 +112,41 @@ func convertAssign(dest, src interface{}) error { if d == nil { return errNilPtr } - bcopy := make([]byte, len(s)) - copy(bcopy, s) - *d = bcopy + *d = cloneBytes(s) return nil case *[]byte: if d == nil { return errNilPtr } + *d = cloneBytes(s) + return nil + case *RawBytes: + if d == nil { + return errNilPtr + } *d = s return nil } case nil: switch d := dest.(type) { + case *interface{}: + if d == nil { + return errNilPtr + } + *d = nil + return nil case *[]byte: if d == nil { return errNilPtr } *d = nil return nil + case *RawBytes: + if d == nil { + return errNilPtr + } + *d = nil + return nil } } @@ -141,6 +163,26 @@ func convertAssign(dest, src interface{}) error { *d = fmt.Sprintf("%v", src) return nil } + case *[]byte: + sv = reflect.ValueOf(src) + switch sv.Kind() { + case reflect.Bool, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, + reflect.Float32, reflect.Float64: + *d = []byte(fmt.Sprintf("%v", src)) + return nil + } + case *RawBytes: + sv = reflect.ValueOf(src) + switch sv.Kind() { + case reflect.Bool, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, + reflect.Float32, reflect.Float64: + *d = RawBytes(fmt.Sprintf("%v", src)) + return nil + } case *bool: bv, err := driver.Bool.ConvertValue(src) if err == nil { @@ -212,6 +254,16 @@ func convertAssign(dest, src interface{}) error { return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest) } +func cloneBytes(b []byte) []byte { + if b == nil { + return nil + } else { + c := make([]byte, len(b)) + copy(c, b) + return c + } +} + func asString(src interface{}) string { switch v := src.(type) { case string: |