...

Source file src/github.com/jackc/pgtype/composite_fields.go

Documentation: github.com/jackc/pgtype

     1  package pgtype
     2  
     3  import "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.
    10  type CompositeFields []interface{}
    11  
    12  func (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  
    34  func (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.
    58  func (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.
    82  func (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  

View as plain text