pgxtype-experiment
Jack Christensen 2017-02-17 22:20:18 -06:00
parent 366440d40d
commit 4faf97cc58
2 changed files with 28 additions and 1 deletions

View File

@ -219,6 +219,15 @@ func (rows *Rows) Scan(dest ...interface{}) (err error) {
if err != nil {
rows.Fatal(scanArgError{col: i, err: err})
}
} else if s, ok := d.(ScannerV3); ok {
val, err := decodeByOID(vr)
if err != nil {
rows.Fatal(scanArgError{col: i, err: err})
}
err = s.ScanPgxV3(nil, val)
if err != nil {
rows.Fatal(scanArgError{col: i, err: err})
}
} else if s, ok := d.(sql.Scanner); ok {
var val interface{}
if 0 <= vr.Len() {
@ -296,7 +305,7 @@ func (rows *Rows) Values() ([]interface{}, error) {
values = append(values, nil)
continue
}
// TODO - consider what are the implications of returning complex types since database/sql uses this method
switch vr.Type().FormatCode {
// All intrinsic types (except string) are encoded with binary
// encoding so anything else should be treated as a string

View File

@ -200,6 +200,10 @@ type Encoder interface {
FormatCode() int16
}
type ScannerV3 interface {
ScanPgxV3(fieldDescription interface{}, src interface{}) error
}
// NullFloat32 represents an float4 that may be null. NullFloat32 implements the
// Scanner and Encoder interfaces so it may be used both as an argument to
// Query[Row] and a destination for Scan.
@ -1166,6 +1170,20 @@ func stripNamedType(val *reflect.Value) (interface{}, bool) {
return nil, false
}
func decodeByOID(vr *ValueReader) (interface{}, error) {
switch vr.Type().DataType {
case Int2OID, Int4OID, Int8OID:
n := decodeInt(vr)
return n, vr.Err()
case BoolOID:
b := decodeBool(vr)
return b, vr.Err()
default:
buf := vr.ReadBytes(vr.Len())
return buf, vr.Err()
}
}
// Decode decodes from vr into d. d must be a pointer. This allows
// implementations of the Decoder interface to delegate the actual work of
// decoding to the built-in functionality.