1package pgtype 2 3import "fmt" 4 5// CompositeFields scans the fields of a composite type into the elements of the CompositeFields value. To scan a 6// nullable value use a *CompositeFields. It will be set to nil in case of null. 7// 8// CompositeFields implements EncodeBinary and EncodeText. However, functionality is limited due to CompositeFields not 9// knowing the PostgreSQL schema of the composite type. Prefer using a registered CompositeType. 10type CompositeFields []interface{} 11 12func (cf CompositeFields) DecodeBinary(ci *ConnInfo, src []byte) error { 13 if len(cf) == 0 { 14 return fmt.Errorf("cannot decode into empty CompositeFields") 15 } 16 17 if src == nil { 18 return fmt.Errorf("cannot decode unexpected null into CompositeFields") 19 } 20 21 scanner := NewCompositeBinaryScanner(ci, src) 22 23 for _, f := range cf { 24 scanner.ScanValue(f) 25 } 26 27 if scanner.Err() != nil { 28 return scanner.Err() 29 } 30 31 return nil 32} 33 34func (cf CompositeFields) DecodeText(ci *ConnInfo, src []byte) error { 35 if len(cf) == 0 { 36 return fmt.Errorf("cannot decode into empty CompositeFields") 37 } 38 39 if src == nil { 40 return fmt.Errorf("cannot decode unexpected null into CompositeFields") 41 } 42 43 scanner := NewCompositeTextScanner(ci, src) 44 45 for _, f := range cf { 46 scanner.ScanValue(f) 47 } 48 49 if scanner.Err() != nil { 50 return scanner.Err() 51 } 52 53 return nil 54} 55 56// EncodeText encodes composite fields into the text format. Prefer registering a CompositeType to using 57// CompositeFields to encode directly. 58func (cf CompositeFields) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) { 59 b := NewCompositeTextBuilder(ci, buf) 60 61 for _, f := range cf { 62 if textEncoder, ok := f.(TextEncoder); ok { 63 b.AppendEncoder(textEncoder) 64 } else { 65 b.AppendValue(f) 66 } 67 } 68 69 return b.Finish() 70} 71 72// EncodeBinary encodes composite fields into the binary format. Unlike CompositeType the schema of the destination is 73// unknown. Prefer registering a CompositeType to using CompositeFields to encode directly. Because the binary 74// composite format requires the OID of each field to be specified the only types that will work are those known to 75// ConnInfo. 76// 77// In particular: 78// 79// * Nil cannot be used because there is no way to determine what type it. 80// * Integer types must be exact matches. e.g. A Go int32 into a PostgreSQL bigint will fail. 81// * No dereferencing will be done. e.g. *Text must be used instead of Text. 82func (cf CompositeFields) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) { 83 b := NewCompositeBinaryBuilder(ci, buf) 84 85 for _, f := range cf { 86 dt, ok := ci.DataTypeForValue(f) 87 if !ok { 88 return nil, fmt.Errorf("Unknown OID for %#v", f) 89 } 90 91 if binaryEncoder, ok := f.(BinaryEncoder); ok { 92 b.AppendEncoder(dt.OID, binaryEncoder) 93 } else { 94 err := dt.Value.Set(f) 95 if err != nil { 96 return nil, err 97 } 98 if binaryEncoder, ok := dt.Value.(BinaryEncoder); ok { 99 b.AppendEncoder(dt.OID, binaryEncoder) 100 } else { 101 return nil, fmt.Errorf("Cannot encode binary format for %v", f) 102 } 103 } 104 } 105 106 return b.Finish() 107} 108