...

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

Documentation: github.com/jackc/pgtype

     1  package pgtype
     2  
     3  import (
     4  	"database/sql/driver"
     5  	"encoding/binary"
     6  	"fmt"
     7  
     8  	"github.com/jackc/pgio"
     9  )
    10  
    11  type Nummultirange struct {
    12  	Ranges []Numrange
    13  	Status Status
    14  }
    15  
    16  func (dst *Nummultirange) Set(src interface{}) error {
    17  	//untyped nil and typed nil interfaces are different
    18  	if src == nil {
    19  		*dst = Nummultirange{Status: Null}
    20  		return nil
    21  	}
    22  
    23  	switch value := src.(type) {
    24  	case Nummultirange:
    25  		*dst = value
    26  	case *Nummultirange:
    27  		*dst = *value
    28  	case string:
    29  		return dst.DecodeText(nil, []byte(value))
    30  	case []Numrange:
    31  		if value == nil {
    32  			*dst = Nummultirange{Status: Null}
    33  		} else if len(value) == 0 {
    34  			*dst = Nummultirange{Status: Present}
    35  		} else {
    36  			elements := make([]Numrange, len(value))
    37  			for i := range value {
    38  				if err := elements[i].Set(value[i]); err != nil {
    39  					return err
    40  				}
    41  			}
    42  			*dst = Nummultirange{
    43  				Ranges: elements,
    44  				Status: Present,
    45  			}
    46  		}
    47  	case []*Numrange:
    48  		if value == nil {
    49  			*dst = Nummultirange{Status: Null}
    50  		} else if len(value) == 0 {
    51  			*dst = Nummultirange{Status: Present}
    52  		} else {
    53  			elements := make([]Numrange, len(value))
    54  			for i := range value {
    55  				if err := elements[i].Set(value[i]); err != nil {
    56  					return err
    57  				}
    58  			}
    59  			*dst = Nummultirange{
    60  				Ranges: elements,
    61  				Status: Present,
    62  			}
    63  		}
    64  	default:
    65  		return fmt.Errorf("cannot convert %v to Nummultirange", src)
    66  	}
    67  
    68  	return nil
    69  
    70  }
    71  
    72  func (dst Nummultirange) Get() interface{} {
    73  	switch dst.Status {
    74  	case Present:
    75  		return dst
    76  	case Null:
    77  		return nil
    78  	default:
    79  		return dst.Status
    80  	}
    81  }
    82  
    83  func (src *Nummultirange) AssignTo(dst interface{}) error {
    84  	return fmt.Errorf("cannot assign %v to %T", src, dst)
    85  }
    86  
    87  func (dst *Nummultirange) DecodeText(ci *ConnInfo, src []byte) error {
    88  	if src == nil {
    89  		*dst = Nummultirange{Status: Null}
    90  		return nil
    91  	}
    92  
    93  	utmr, err := ParseUntypedTextMultirange(string(src))
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	var elements []Numrange
    99  
   100  	if len(utmr.Elements) > 0 {
   101  		elements = make([]Numrange, len(utmr.Elements))
   102  
   103  		for i, s := range utmr.Elements {
   104  			var elem Numrange
   105  
   106  			elemSrc := []byte(s)
   107  
   108  			err = elem.DecodeText(ci, elemSrc)
   109  			if err != nil {
   110  				return err
   111  			}
   112  
   113  			elements[i] = elem
   114  		}
   115  	}
   116  
   117  	*dst = Nummultirange{Ranges: elements, Status: Present}
   118  
   119  	return nil
   120  }
   121  
   122  func (dst *Nummultirange) DecodeBinary(ci *ConnInfo, src []byte) error {
   123  	if src == nil {
   124  		*dst = Nummultirange{Status: Null}
   125  		return nil
   126  	}
   127  
   128  	rp := 0
   129  
   130  	numElems := int(binary.BigEndian.Uint32(src[rp:]))
   131  	rp += 4
   132  
   133  	if numElems == 0 {
   134  		*dst = Nummultirange{Status: Present}
   135  		return nil
   136  	}
   137  
   138  	elements := make([]Numrange, numElems)
   139  
   140  	for i := range elements {
   141  		elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
   142  		rp += 4
   143  		var elemSrc []byte
   144  		if elemLen >= 0 {
   145  			elemSrc = src[rp : rp+elemLen]
   146  			rp += elemLen
   147  		}
   148  		err := elements[i].DecodeBinary(ci, elemSrc)
   149  		if err != nil {
   150  			return err
   151  		}
   152  	}
   153  
   154  	*dst = Nummultirange{Ranges: elements, Status: Present}
   155  	return nil
   156  }
   157  
   158  func (src Nummultirange) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
   159  	switch src.Status {
   160  	case Null:
   161  		return nil, nil
   162  	case Undefined:
   163  		return nil, errUndefined
   164  	}
   165  
   166  	buf = append(buf, '{')
   167  
   168  	inElemBuf := make([]byte, 0, 32)
   169  	for i, elem := range src.Ranges {
   170  		if i > 0 {
   171  			buf = append(buf, ',')
   172  		}
   173  
   174  		elemBuf, err := elem.EncodeText(ci, inElemBuf)
   175  		if err != nil {
   176  			return nil, err
   177  		}
   178  		if elemBuf == nil {
   179  			return nil, fmt.Errorf("multi-range does not allow null range")
   180  		} else {
   181  			buf = append(buf, string(elemBuf)...)
   182  		}
   183  
   184  	}
   185  
   186  	buf = append(buf, '}')
   187  
   188  	return buf, nil
   189  }
   190  
   191  func (src Nummultirange) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
   192  	switch src.Status {
   193  	case Null:
   194  		return nil, nil
   195  	case Undefined:
   196  		return nil, errUndefined
   197  	}
   198  
   199  	buf = pgio.AppendInt32(buf, int32(len(src.Ranges)))
   200  
   201  	for i := range src.Ranges {
   202  		sp := len(buf)
   203  		buf = pgio.AppendInt32(buf, -1)
   204  
   205  		elemBuf, err := src.Ranges[i].EncodeBinary(ci, buf)
   206  		if err != nil {
   207  			return nil, err
   208  		}
   209  		if elemBuf != nil {
   210  			buf = elemBuf
   211  			pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
   212  		}
   213  	}
   214  
   215  	return buf, nil
   216  }
   217  
   218  // Scan implements the database/sql Scanner interface.
   219  func (dst *Nummultirange) Scan(src interface{}) error {
   220  	if src == nil {
   221  		return dst.DecodeText(nil, nil)
   222  	}
   223  
   224  	switch src := src.(type) {
   225  	case string:
   226  		return dst.DecodeText(nil, []byte(src))
   227  	case []byte:
   228  		srcCopy := make([]byte, len(src))
   229  		copy(srcCopy, src)
   230  		return dst.DecodeText(nil, srcCopy)
   231  	}
   232  
   233  	return fmt.Errorf("cannot scan %T", src)
   234  }
   235  
   236  // Value implements the database/sql/driver Valuer interface.
   237  func (src Nummultirange) Value() (driver.Value, error) {
   238  	return EncodeValueText(src)
   239  }
   240  

View as plain text