...

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

Documentation: github.com/jackc/pgtype

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

View as plain text