1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
package pgtype
import (
"fmt"
"reflect"
)
// Record is the generic PostgreSQL record type such as is created with the
// "row" function. Record only implements BinaryEncoder and Value. The text
// format output format from PostgreSQL does not include type information and is
// therefore impossible to decode. No encoders are implemented because
// PostgreSQL does not support input of generic records.
type Record struct {
Fields []Value
Status Status
}
func (dst *Record) Set(src interface{}) error {
if src == nil {
*dst = Record{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case []Value:
*dst = Record{Fields: value, Status: Present}
default:
return fmt.Errorf("cannot convert %v to Record", src)
}
return nil
}
func (dst Record) Get() interface{} {
switch dst.Status {
case Present:
return dst.Fields
case Null:
return nil
default:
return dst.Status
}
}
func (src *Record) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *[]Value:
*v = make([]Value, len(src.Fields))
copy(*v, src.Fields)
return nil
case *[]interface{}:
*v = make([]interface{}, len(src.Fields))
for i := range *v {
(*v)[i] = src.Fields[i].Get()
}
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func prepareNewBinaryDecoder(ci *ConnInfo, fieldOID uint32, v *Value) (BinaryDecoder, error) {
var binaryDecoder BinaryDecoder
if dt, ok := ci.DataTypeForOID(fieldOID); ok {
binaryDecoder, _ = dt.Value.(BinaryDecoder)
} else {
return nil, fmt.Errorf("unknown oid while decoding record: %v", fieldOID)
}
if binaryDecoder == nil {
return nil, fmt.Errorf("no binary decoder registered for: %v", fieldOID)
}
// Duplicate struct to scan into
binaryDecoder = reflect.New(reflect.ValueOf(binaryDecoder).Elem().Type()).Interface().(BinaryDecoder)
*v = binaryDecoder.(Value)
return binaryDecoder, nil
}
func (dst *Record) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Record{Status: Null}
return nil
}
scanner := NewCompositeBinaryScanner(ci, src)
fields := make([]Value, scanner.FieldCount())
for i := 0; scanner.Next(); i++ {
binaryDecoder, err := prepareNewBinaryDecoder(ci, scanner.OID(), &fields[i])
if err != nil {
return err
}
if err = binaryDecoder.DecodeBinary(ci, scanner.Bytes()); err != nil {
return err
}
}
if scanner.Err() != nil {
return scanner.Err()
}
*dst = Record{Fields: fields, Status: Present}
return nil
}
|