...

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

Documentation: github.com/jackc/pgtype

     1  // Code generated by erb. DO NOT EDIT.
     2  
     3  package pgtype
     4  
     5  import (
     6  	"database/sql/driver"
     7  	"encoding/binary"
     8  	"fmt"
     9  	"reflect"
    10  
    11  	"github.com/jackc/pgio"
    12  )
    13  
    14  type TstzrangeArray struct {
    15  	Elements   []Tstzrange
    16  	Dimensions []ArrayDimension
    17  	Status     Status
    18  }
    19  
    20  func (dst *TstzrangeArray) Set(src interface{}) error {
    21  	// untyped nil and typed nil interfaces are different
    22  	if src == nil {
    23  		*dst = TstzrangeArray{Status: Null}
    24  		return nil
    25  	}
    26  
    27  	if value, ok := src.(interface{ Get() interface{} }); ok {
    28  		value2 := value.Get()
    29  		if value2 != value {
    30  			return dst.Set(value2)
    31  		}
    32  	}
    33  
    34  	// Attempt to match to select common types:
    35  	switch value := src.(type) {
    36  
    37  	case []Tstzrange:
    38  		if value == nil {
    39  			*dst = TstzrangeArray{Status: Null}
    40  		} else if len(value) == 0 {
    41  			*dst = TstzrangeArray{Status: Present}
    42  		} else {
    43  			*dst = TstzrangeArray{
    44  				Elements:   value,
    45  				Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
    46  				Status:     Present,
    47  			}
    48  		}
    49  	default:
    50  		// Fallback to reflection if an optimised match was not found.
    51  		// The reflection is necessary for arrays and multidimensional slices,
    52  		// but it comes with a 20-50% performance penalty for large arrays/slices
    53  		reflectedValue := reflect.ValueOf(src)
    54  		if !reflectedValue.IsValid() || reflectedValue.IsZero() {
    55  			*dst = TstzrangeArray{Status: Null}
    56  			return nil
    57  		}
    58  
    59  		dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
    60  		if !ok {
    61  			return fmt.Errorf("cannot find dimensions of %v for TstzrangeArray", src)
    62  		}
    63  		if elementsLength == 0 {
    64  			*dst = TstzrangeArray{Status: Present}
    65  			return nil
    66  		}
    67  		if len(dimensions) == 0 {
    68  			if originalSrc, ok := underlyingSliceType(src); ok {
    69  				return dst.Set(originalSrc)
    70  			}
    71  			return fmt.Errorf("cannot convert %v to TstzrangeArray", src)
    72  		}
    73  
    74  		*dst = TstzrangeArray{
    75  			Elements:   make([]Tstzrange, elementsLength),
    76  			Dimensions: dimensions,
    77  			Status:     Present,
    78  		}
    79  		elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
    80  		if err != nil {
    81  			// Maybe the target was one dimension too far, try again:
    82  			if len(dst.Dimensions) > 1 {
    83  				dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
    84  				elementsLength = 0
    85  				for _, dim := range dst.Dimensions {
    86  					if elementsLength == 0 {
    87  						elementsLength = int(dim.Length)
    88  					} else {
    89  						elementsLength *= int(dim.Length)
    90  					}
    91  				}
    92  				dst.Elements = make([]Tstzrange, elementsLength)
    93  				elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
    94  				if err != nil {
    95  					return err
    96  				}
    97  			} else {
    98  				return err
    99  			}
   100  		}
   101  		if elementCount != len(dst.Elements) {
   102  			return fmt.Errorf("cannot convert %v to TstzrangeArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
   103  		}
   104  	}
   105  
   106  	return nil
   107  }
   108  
   109  func (dst *TstzrangeArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
   110  	switch value.Kind() {
   111  	case reflect.Array:
   112  		fallthrough
   113  	case reflect.Slice:
   114  		if len(dst.Dimensions) == dimension {
   115  			break
   116  		}
   117  
   118  		valueLen := value.Len()
   119  		if int32(valueLen) != dst.Dimensions[dimension].Length {
   120  			return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
   121  		}
   122  		for i := 0; i < valueLen; i++ {
   123  			var err error
   124  			index, err = dst.setRecursive(value.Index(i), index, dimension+1)
   125  			if err != nil {
   126  				return 0, err
   127  			}
   128  		}
   129  
   130  		return index, nil
   131  	}
   132  	if !value.CanInterface() {
   133  		return 0, fmt.Errorf("cannot convert all values to TstzrangeArray")
   134  	}
   135  	if err := dst.Elements[index].Set(value.Interface()); err != nil {
   136  		return 0, fmt.Errorf("%v in TstzrangeArray", err)
   137  	}
   138  	index++
   139  
   140  	return index, nil
   141  }
   142  
   143  func (dst TstzrangeArray) Get() interface{} {
   144  	switch dst.Status {
   145  	case Present:
   146  		return dst
   147  	case Null:
   148  		return nil
   149  	default:
   150  		return dst.Status
   151  	}
   152  }
   153  
   154  func (src *TstzrangeArray) AssignTo(dst interface{}) error {
   155  	switch src.Status {
   156  	case Present:
   157  		if len(src.Dimensions) <= 1 {
   158  			// Attempt to match to select common types:
   159  			switch v := dst.(type) {
   160  
   161  			case *[]Tstzrange:
   162  				*v = make([]Tstzrange, len(src.Elements))
   163  				for i := range src.Elements {
   164  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   165  						return err
   166  					}
   167  				}
   168  				return nil
   169  
   170  			}
   171  		}
   172  
   173  		// Try to convert to something AssignTo can use directly.
   174  		if nextDst, retry := GetAssignToDstType(dst); retry {
   175  			return src.AssignTo(nextDst)
   176  		}
   177  
   178  		// Fallback to reflection if an optimised match was not found.
   179  		// The reflection is necessary for arrays and multidimensional slices,
   180  		// but it comes with a 20-50% performance penalty for large arrays/slices
   181  		value := reflect.ValueOf(dst)
   182  		if value.Kind() == reflect.Ptr {
   183  			value = value.Elem()
   184  		}
   185  
   186  		switch value.Kind() {
   187  		case reflect.Array, reflect.Slice:
   188  		default:
   189  			return fmt.Errorf("cannot assign %T to %T", src, dst)
   190  		}
   191  
   192  		if len(src.Elements) == 0 {
   193  			if value.Kind() == reflect.Slice {
   194  				value.Set(reflect.MakeSlice(value.Type(), 0, 0))
   195  				return nil
   196  			}
   197  		}
   198  
   199  		elementCount, err := src.assignToRecursive(value, 0, 0)
   200  		if err != nil {
   201  			return err
   202  		}
   203  		if elementCount != len(src.Elements) {
   204  			return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
   205  		}
   206  
   207  		return nil
   208  	case Null:
   209  		return NullAssignTo(dst)
   210  	}
   211  
   212  	return fmt.Errorf("cannot decode %#v into %T", src, dst)
   213  }
   214  
   215  func (src *TstzrangeArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
   216  	switch kind := value.Kind(); kind {
   217  	case reflect.Array:
   218  		fallthrough
   219  	case reflect.Slice:
   220  		if len(src.Dimensions) == dimension {
   221  			break
   222  		}
   223  
   224  		length := int(src.Dimensions[dimension].Length)
   225  		if reflect.Array == kind {
   226  			typ := value.Type()
   227  			if typ.Len() != length {
   228  				return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
   229  			}
   230  			value.Set(reflect.New(typ).Elem())
   231  		} else {
   232  			value.Set(reflect.MakeSlice(value.Type(), length, length))
   233  		}
   234  
   235  		var err error
   236  		for i := 0; i < length; i++ {
   237  			index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
   238  			if err != nil {
   239  				return 0, err
   240  			}
   241  		}
   242  
   243  		return index, nil
   244  	}
   245  	if len(src.Dimensions) != dimension {
   246  		return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
   247  	}
   248  	if !value.CanAddr() {
   249  		return 0, fmt.Errorf("cannot assign all values from TstzrangeArray")
   250  	}
   251  	addr := value.Addr()
   252  	if !addr.CanInterface() {
   253  		return 0, fmt.Errorf("cannot assign all values from TstzrangeArray")
   254  	}
   255  	if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
   256  		return 0, err
   257  	}
   258  	index++
   259  	return index, nil
   260  }
   261  
   262  func (dst *TstzrangeArray) DecodeText(ci *ConnInfo, src []byte) error {
   263  	if src == nil {
   264  		*dst = TstzrangeArray{Status: Null}
   265  		return nil
   266  	}
   267  
   268  	uta, err := ParseUntypedTextArray(string(src))
   269  	if err != nil {
   270  		return err
   271  	}
   272  
   273  	var elements []Tstzrange
   274  
   275  	if len(uta.Elements) > 0 {
   276  		elements = make([]Tstzrange, len(uta.Elements))
   277  
   278  		for i, s := range uta.Elements {
   279  			var elem Tstzrange
   280  			var elemSrc []byte
   281  			if s != "NULL" || uta.Quoted[i] {
   282  				elemSrc = []byte(s)
   283  			}
   284  			err = elem.DecodeText(ci, elemSrc)
   285  			if err != nil {
   286  				return err
   287  			}
   288  
   289  			elements[i] = elem
   290  		}
   291  	}
   292  
   293  	*dst = TstzrangeArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
   294  
   295  	return nil
   296  }
   297  
   298  func (dst *TstzrangeArray) DecodeBinary(ci *ConnInfo, src []byte) error {
   299  	if src == nil {
   300  		*dst = TstzrangeArray{Status: Null}
   301  		return nil
   302  	}
   303  
   304  	var arrayHeader ArrayHeader
   305  	rp, err := arrayHeader.DecodeBinary(ci, src)
   306  	if err != nil {
   307  		return err
   308  	}
   309  
   310  	if len(arrayHeader.Dimensions) == 0 {
   311  		*dst = TstzrangeArray{Dimensions: arrayHeader.Dimensions, Status: Present}
   312  		return nil
   313  	}
   314  
   315  	elementCount := arrayHeader.Dimensions[0].Length
   316  	for _, d := range arrayHeader.Dimensions[1:] {
   317  		elementCount *= d.Length
   318  	}
   319  
   320  	elements := make([]Tstzrange, elementCount)
   321  
   322  	for i := range elements {
   323  		elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
   324  		rp += 4
   325  		var elemSrc []byte
   326  		if elemLen >= 0 {
   327  			elemSrc = src[rp : rp+elemLen]
   328  			rp += elemLen
   329  		}
   330  		err = elements[i].DecodeBinary(ci, elemSrc)
   331  		if err != nil {
   332  			return err
   333  		}
   334  	}
   335  
   336  	*dst = TstzrangeArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
   337  	return nil
   338  }
   339  
   340  func (src TstzrangeArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
   341  	switch src.Status {
   342  	case Null:
   343  		return nil, nil
   344  	case Undefined:
   345  		return nil, errUndefined
   346  	}
   347  
   348  	if len(src.Dimensions) == 0 {
   349  		return append(buf, '{', '}'), nil
   350  	}
   351  
   352  	buf = EncodeTextArrayDimensions(buf, src.Dimensions)
   353  
   354  	// dimElemCounts is the multiples of elements that each array lies on. For
   355  	// example, a single dimension array of length 4 would have a dimElemCounts of
   356  	// [4]. A multi-dimensional array of lengths [3,5,2] would have a
   357  	// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
   358  	// or '}'.
   359  	dimElemCounts := make([]int, len(src.Dimensions))
   360  	dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
   361  	for i := len(src.Dimensions) - 2; i > -1; i-- {
   362  		dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
   363  	}
   364  
   365  	inElemBuf := make([]byte, 0, 32)
   366  	for i, elem := range src.Elements {
   367  		if i > 0 {
   368  			buf = append(buf, ',')
   369  		}
   370  
   371  		for _, dec := range dimElemCounts {
   372  			if i%dec == 0 {
   373  				buf = append(buf, '{')
   374  			}
   375  		}
   376  
   377  		elemBuf, err := elem.EncodeText(ci, inElemBuf)
   378  		if err != nil {
   379  			return nil, err
   380  		}
   381  		if elemBuf == nil {
   382  			buf = append(buf, `NULL`...)
   383  		} else {
   384  			buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
   385  		}
   386  
   387  		for _, dec := range dimElemCounts {
   388  			if (i+1)%dec == 0 {
   389  				buf = append(buf, '}')
   390  			}
   391  		}
   392  	}
   393  
   394  	return buf, nil
   395  }
   396  
   397  func (src TstzrangeArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
   398  	switch src.Status {
   399  	case Null:
   400  		return nil, nil
   401  	case Undefined:
   402  		return nil, errUndefined
   403  	}
   404  
   405  	arrayHeader := ArrayHeader{
   406  		Dimensions: src.Dimensions,
   407  	}
   408  
   409  	if dt, ok := ci.DataTypeForName("tstzrange"); ok {
   410  		arrayHeader.ElementOID = int32(dt.OID)
   411  	} else {
   412  		return nil, fmt.Errorf("unable to find oid for type name %v", "tstzrange")
   413  	}
   414  
   415  	for i := range src.Elements {
   416  		if src.Elements[i].Status == Null {
   417  			arrayHeader.ContainsNull = true
   418  			break
   419  		}
   420  	}
   421  
   422  	buf = arrayHeader.EncodeBinary(ci, buf)
   423  
   424  	for i := range src.Elements {
   425  		sp := len(buf)
   426  		buf = pgio.AppendInt32(buf, -1)
   427  
   428  		elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
   429  		if err != nil {
   430  			return nil, err
   431  		}
   432  		if elemBuf != nil {
   433  			buf = elemBuf
   434  			pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
   435  		}
   436  	}
   437  
   438  	return buf, nil
   439  }
   440  
   441  // Scan implements the database/sql Scanner interface.
   442  func (dst *TstzrangeArray) Scan(src interface{}) error {
   443  	if src == nil {
   444  		return dst.DecodeText(nil, nil)
   445  	}
   446  
   447  	switch src := src.(type) {
   448  	case string:
   449  		return dst.DecodeText(nil, []byte(src))
   450  	case []byte:
   451  		srcCopy := make([]byte, len(src))
   452  		copy(srcCopy, src)
   453  		return dst.DecodeText(nil, srcCopy)
   454  	}
   455  
   456  	return fmt.Errorf("cannot scan %T", src)
   457  }
   458  
   459  // Value implements the database/sql/driver Valuer interface.
   460  func (src TstzrangeArray) Value() (driver.Value, error) {
   461  	buf, err := src.EncodeText(nil, nil)
   462  	if err != nil {
   463  		return nil, err
   464  	}
   465  	if buf == nil {
   466  		return nil, nil
   467  	}
   468  
   469  	return string(buf), nil
   470  }
   471  

View as plain text