...

Source file src/github.com/jackc/pgtype/int4_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 Int4Array struct {
    15  	Elements   []Int4
    16  	Dimensions []ArrayDimension
    17  	Status     Status
    18  }
    19  
    20  func (dst *Int4Array) Set(src interface{}) error {
    21  	// untyped nil and typed nil interfaces are different
    22  	if src == nil {
    23  		*dst = Int4Array{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 []int16:
    38  		if value == nil {
    39  			*dst = Int4Array{Status: Null}
    40  		} else if len(value) == 0 {
    41  			*dst = Int4Array{Status: Present}
    42  		} else {
    43  			elements := make([]Int4, len(value))
    44  			for i := range value {
    45  				if err := elements[i].Set(value[i]); err != nil {
    46  					return err
    47  				}
    48  			}
    49  			*dst = Int4Array{
    50  				Elements:   elements,
    51  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
    52  				Status:     Present,
    53  			}
    54  		}
    55  
    56  	case []*int16:
    57  		if value == nil {
    58  			*dst = Int4Array{Status: Null}
    59  		} else if len(value) == 0 {
    60  			*dst = Int4Array{Status: Present}
    61  		} else {
    62  			elements := make([]Int4, len(value))
    63  			for i := range value {
    64  				if err := elements[i].Set(value[i]); err != nil {
    65  					return err
    66  				}
    67  			}
    68  			*dst = Int4Array{
    69  				Elements:   elements,
    70  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
    71  				Status:     Present,
    72  			}
    73  		}
    74  
    75  	case []uint16:
    76  		if value == nil {
    77  			*dst = Int4Array{Status: Null}
    78  		} else if len(value) == 0 {
    79  			*dst = Int4Array{Status: Present}
    80  		} else {
    81  			elements := make([]Int4, len(value))
    82  			for i := range value {
    83  				if err := elements[i].Set(value[i]); err != nil {
    84  					return err
    85  				}
    86  			}
    87  			*dst = Int4Array{
    88  				Elements:   elements,
    89  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
    90  				Status:     Present,
    91  			}
    92  		}
    93  
    94  	case []*uint16:
    95  		if value == nil {
    96  			*dst = Int4Array{Status: Null}
    97  		} else if len(value) == 0 {
    98  			*dst = Int4Array{Status: Present}
    99  		} else {
   100  			elements := make([]Int4, len(value))
   101  			for i := range value {
   102  				if err := elements[i].Set(value[i]); err != nil {
   103  					return err
   104  				}
   105  			}
   106  			*dst = Int4Array{
   107  				Elements:   elements,
   108  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   109  				Status:     Present,
   110  			}
   111  		}
   112  
   113  	case []int32:
   114  		if value == nil {
   115  			*dst = Int4Array{Status: Null}
   116  		} else if len(value) == 0 {
   117  			*dst = Int4Array{Status: Present}
   118  		} else {
   119  			elements := make([]Int4, len(value))
   120  			for i := range value {
   121  				if err := elements[i].Set(value[i]); err != nil {
   122  					return err
   123  				}
   124  			}
   125  			*dst = Int4Array{
   126  				Elements:   elements,
   127  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   128  				Status:     Present,
   129  			}
   130  		}
   131  
   132  	case []*int32:
   133  		if value == nil {
   134  			*dst = Int4Array{Status: Null}
   135  		} else if len(value) == 0 {
   136  			*dst = Int4Array{Status: Present}
   137  		} else {
   138  			elements := make([]Int4, len(value))
   139  			for i := range value {
   140  				if err := elements[i].Set(value[i]); err != nil {
   141  					return err
   142  				}
   143  			}
   144  			*dst = Int4Array{
   145  				Elements:   elements,
   146  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   147  				Status:     Present,
   148  			}
   149  		}
   150  
   151  	case []uint32:
   152  		if value == nil {
   153  			*dst = Int4Array{Status: Null}
   154  		} else if len(value) == 0 {
   155  			*dst = Int4Array{Status: Present}
   156  		} else {
   157  			elements := make([]Int4, len(value))
   158  			for i := range value {
   159  				if err := elements[i].Set(value[i]); err != nil {
   160  					return err
   161  				}
   162  			}
   163  			*dst = Int4Array{
   164  				Elements:   elements,
   165  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   166  				Status:     Present,
   167  			}
   168  		}
   169  
   170  	case []*uint32:
   171  		if value == nil {
   172  			*dst = Int4Array{Status: Null}
   173  		} else if len(value) == 0 {
   174  			*dst = Int4Array{Status: Present}
   175  		} else {
   176  			elements := make([]Int4, len(value))
   177  			for i := range value {
   178  				if err := elements[i].Set(value[i]); err != nil {
   179  					return err
   180  				}
   181  			}
   182  			*dst = Int4Array{
   183  				Elements:   elements,
   184  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   185  				Status:     Present,
   186  			}
   187  		}
   188  
   189  	case []int64:
   190  		if value == nil {
   191  			*dst = Int4Array{Status: Null}
   192  		} else if len(value) == 0 {
   193  			*dst = Int4Array{Status: Present}
   194  		} else {
   195  			elements := make([]Int4, len(value))
   196  			for i := range value {
   197  				if err := elements[i].Set(value[i]); err != nil {
   198  					return err
   199  				}
   200  			}
   201  			*dst = Int4Array{
   202  				Elements:   elements,
   203  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   204  				Status:     Present,
   205  			}
   206  		}
   207  
   208  	case []*int64:
   209  		if value == nil {
   210  			*dst = Int4Array{Status: Null}
   211  		} else if len(value) == 0 {
   212  			*dst = Int4Array{Status: Present}
   213  		} else {
   214  			elements := make([]Int4, len(value))
   215  			for i := range value {
   216  				if err := elements[i].Set(value[i]); err != nil {
   217  					return err
   218  				}
   219  			}
   220  			*dst = Int4Array{
   221  				Elements:   elements,
   222  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   223  				Status:     Present,
   224  			}
   225  		}
   226  
   227  	case []uint64:
   228  		if value == nil {
   229  			*dst = Int4Array{Status: Null}
   230  		} else if len(value) == 0 {
   231  			*dst = Int4Array{Status: Present}
   232  		} else {
   233  			elements := make([]Int4, len(value))
   234  			for i := range value {
   235  				if err := elements[i].Set(value[i]); err != nil {
   236  					return err
   237  				}
   238  			}
   239  			*dst = Int4Array{
   240  				Elements:   elements,
   241  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   242  				Status:     Present,
   243  			}
   244  		}
   245  
   246  	case []*uint64:
   247  		if value == nil {
   248  			*dst = Int4Array{Status: Null}
   249  		} else if len(value) == 0 {
   250  			*dst = Int4Array{Status: Present}
   251  		} else {
   252  			elements := make([]Int4, len(value))
   253  			for i := range value {
   254  				if err := elements[i].Set(value[i]); err != nil {
   255  					return err
   256  				}
   257  			}
   258  			*dst = Int4Array{
   259  				Elements:   elements,
   260  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   261  				Status:     Present,
   262  			}
   263  		}
   264  
   265  	case []int:
   266  		if value == nil {
   267  			*dst = Int4Array{Status: Null}
   268  		} else if len(value) == 0 {
   269  			*dst = Int4Array{Status: Present}
   270  		} else {
   271  			elements := make([]Int4, len(value))
   272  			for i := range value {
   273  				if err := elements[i].Set(value[i]); err != nil {
   274  					return err
   275  				}
   276  			}
   277  			*dst = Int4Array{
   278  				Elements:   elements,
   279  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   280  				Status:     Present,
   281  			}
   282  		}
   283  
   284  	case []*int:
   285  		if value == nil {
   286  			*dst = Int4Array{Status: Null}
   287  		} else if len(value) == 0 {
   288  			*dst = Int4Array{Status: Present}
   289  		} else {
   290  			elements := make([]Int4, len(value))
   291  			for i := range value {
   292  				if err := elements[i].Set(value[i]); err != nil {
   293  					return err
   294  				}
   295  			}
   296  			*dst = Int4Array{
   297  				Elements:   elements,
   298  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   299  				Status:     Present,
   300  			}
   301  		}
   302  
   303  	case []uint:
   304  		if value == nil {
   305  			*dst = Int4Array{Status: Null}
   306  		} else if len(value) == 0 {
   307  			*dst = Int4Array{Status: Present}
   308  		} else {
   309  			elements := make([]Int4, len(value))
   310  			for i := range value {
   311  				if err := elements[i].Set(value[i]); err != nil {
   312  					return err
   313  				}
   314  			}
   315  			*dst = Int4Array{
   316  				Elements:   elements,
   317  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   318  				Status:     Present,
   319  			}
   320  		}
   321  
   322  	case []*uint:
   323  		if value == nil {
   324  			*dst = Int4Array{Status: Null}
   325  		} else if len(value) == 0 {
   326  			*dst = Int4Array{Status: Present}
   327  		} else {
   328  			elements := make([]Int4, len(value))
   329  			for i := range value {
   330  				if err := elements[i].Set(value[i]); err != nil {
   331  					return err
   332  				}
   333  			}
   334  			*dst = Int4Array{
   335  				Elements:   elements,
   336  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
   337  				Status:     Present,
   338  			}
   339  		}
   340  
   341  	case []Int4:
   342  		if value == nil {
   343  			*dst = Int4Array{Status: Null}
   344  		} else if len(value) == 0 {
   345  			*dst = Int4Array{Status: Present}
   346  		} else {
   347  			*dst = Int4Array{
   348  				Elements:   value,
   349  				Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
   350  				Status:     Present,
   351  			}
   352  		}
   353  	default:
   354  		// Fallback to reflection if an optimised match was not found.
   355  		// The reflection is necessary for arrays and multidimensional slices,
   356  		// but it comes with a 20-50% performance penalty for large arrays/slices
   357  		reflectedValue := reflect.ValueOf(src)
   358  		if !reflectedValue.IsValid() || reflectedValue.IsZero() {
   359  			*dst = Int4Array{Status: Null}
   360  			return nil
   361  		}
   362  
   363  		dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
   364  		if !ok {
   365  			return fmt.Errorf("cannot find dimensions of %v for Int4Array", src)
   366  		}
   367  		if elementsLength == 0 {
   368  			*dst = Int4Array{Status: Present}
   369  			return nil
   370  		}
   371  		if len(dimensions) == 0 {
   372  			if originalSrc, ok := underlyingSliceType(src); ok {
   373  				return dst.Set(originalSrc)
   374  			}
   375  			return fmt.Errorf("cannot convert %v to Int4Array", src)
   376  		}
   377  
   378  		*dst = Int4Array{
   379  			Elements:   make([]Int4, elementsLength),
   380  			Dimensions: dimensions,
   381  			Status:     Present,
   382  		}
   383  		elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
   384  		if err != nil {
   385  			// Maybe the target was one dimension too far, try again:
   386  			if len(dst.Dimensions) > 1 {
   387  				dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
   388  				elementsLength = 0
   389  				for _, dim := range dst.Dimensions {
   390  					if elementsLength == 0 {
   391  						elementsLength = int(dim.Length)
   392  					} else {
   393  						elementsLength *= int(dim.Length)
   394  					}
   395  				}
   396  				dst.Elements = make([]Int4, elementsLength)
   397  				elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
   398  				if err != nil {
   399  					return err
   400  				}
   401  			} else {
   402  				return err
   403  			}
   404  		}
   405  		if elementCount != len(dst.Elements) {
   406  			return fmt.Errorf("cannot convert %v to Int4Array, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
   407  		}
   408  	}
   409  
   410  	return nil
   411  }
   412  
   413  func (dst *Int4Array) setRecursive(value reflect.Value, index, dimension int) (int, error) {
   414  	switch value.Kind() {
   415  	case reflect.Array:
   416  		fallthrough
   417  	case reflect.Slice:
   418  		if len(dst.Dimensions) == dimension {
   419  			break
   420  		}
   421  
   422  		valueLen := value.Len()
   423  		if int32(valueLen) != dst.Dimensions[dimension].Length {
   424  			return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
   425  		}
   426  		for i := 0; i < valueLen; i++ {
   427  			var err error
   428  			index, err = dst.setRecursive(value.Index(i), index, dimension+1)
   429  			if err != nil {
   430  				return 0, err
   431  			}
   432  		}
   433  
   434  		return index, nil
   435  	}
   436  	if !value.CanInterface() {
   437  		return 0, fmt.Errorf("cannot convert all values to Int4Array")
   438  	}
   439  	if err := dst.Elements[index].Set(value.Interface()); err != nil {
   440  		return 0, fmt.Errorf("%v in Int4Array", err)
   441  	}
   442  	index++
   443  
   444  	return index, nil
   445  }
   446  
   447  func (dst Int4Array) Get() interface{} {
   448  	switch dst.Status {
   449  	case Present:
   450  		return dst
   451  	case Null:
   452  		return nil
   453  	default:
   454  		return dst.Status
   455  	}
   456  }
   457  
   458  func (src *Int4Array) AssignTo(dst interface{}) error {
   459  	switch src.Status {
   460  	case Present:
   461  		if len(src.Dimensions) <= 1 {
   462  			// Attempt to match to select common types:
   463  			switch v := dst.(type) {
   464  
   465  			case *[]int16:
   466  				*v = make([]int16, len(src.Elements))
   467  				for i := range src.Elements {
   468  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   469  						return err
   470  					}
   471  				}
   472  				return nil
   473  
   474  			case *[]*int16:
   475  				*v = make([]*int16, len(src.Elements))
   476  				for i := range src.Elements {
   477  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   478  						return err
   479  					}
   480  				}
   481  				return nil
   482  
   483  			case *[]uint16:
   484  				*v = make([]uint16, len(src.Elements))
   485  				for i := range src.Elements {
   486  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   487  						return err
   488  					}
   489  				}
   490  				return nil
   491  
   492  			case *[]*uint16:
   493  				*v = make([]*uint16, len(src.Elements))
   494  				for i := range src.Elements {
   495  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   496  						return err
   497  					}
   498  				}
   499  				return nil
   500  
   501  			case *[]int32:
   502  				*v = make([]int32, len(src.Elements))
   503  				for i := range src.Elements {
   504  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   505  						return err
   506  					}
   507  				}
   508  				return nil
   509  
   510  			case *[]*int32:
   511  				*v = make([]*int32, len(src.Elements))
   512  				for i := range src.Elements {
   513  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   514  						return err
   515  					}
   516  				}
   517  				return nil
   518  
   519  			case *[]uint32:
   520  				*v = make([]uint32, len(src.Elements))
   521  				for i := range src.Elements {
   522  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   523  						return err
   524  					}
   525  				}
   526  				return nil
   527  
   528  			case *[]*uint32:
   529  				*v = make([]*uint32, len(src.Elements))
   530  				for i := range src.Elements {
   531  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   532  						return err
   533  					}
   534  				}
   535  				return nil
   536  
   537  			case *[]int64:
   538  				*v = make([]int64, len(src.Elements))
   539  				for i := range src.Elements {
   540  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   541  						return err
   542  					}
   543  				}
   544  				return nil
   545  
   546  			case *[]*int64:
   547  				*v = make([]*int64, len(src.Elements))
   548  				for i := range src.Elements {
   549  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   550  						return err
   551  					}
   552  				}
   553  				return nil
   554  
   555  			case *[]uint64:
   556  				*v = make([]uint64, len(src.Elements))
   557  				for i := range src.Elements {
   558  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   559  						return err
   560  					}
   561  				}
   562  				return nil
   563  
   564  			case *[]*uint64:
   565  				*v = make([]*uint64, len(src.Elements))
   566  				for i := range src.Elements {
   567  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   568  						return err
   569  					}
   570  				}
   571  				return nil
   572  
   573  			case *[]int:
   574  				*v = make([]int, len(src.Elements))
   575  				for i := range src.Elements {
   576  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   577  						return err
   578  					}
   579  				}
   580  				return nil
   581  
   582  			case *[]*int:
   583  				*v = make([]*int, len(src.Elements))
   584  				for i := range src.Elements {
   585  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   586  						return err
   587  					}
   588  				}
   589  				return nil
   590  
   591  			case *[]uint:
   592  				*v = make([]uint, len(src.Elements))
   593  				for i := range src.Elements {
   594  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   595  						return err
   596  					}
   597  				}
   598  				return nil
   599  
   600  			case *[]*uint:
   601  				*v = make([]*uint, len(src.Elements))
   602  				for i := range src.Elements {
   603  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   604  						return err
   605  					}
   606  				}
   607  				return nil
   608  
   609  			}
   610  		}
   611  
   612  		// Try to convert to something AssignTo can use directly.
   613  		if nextDst, retry := GetAssignToDstType(dst); retry {
   614  			return src.AssignTo(nextDst)
   615  		}
   616  
   617  		// Fallback to reflection if an optimised match was not found.
   618  		// The reflection is necessary for arrays and multidimensional slices,
   619  		// but it comes with a 20-50% performance penalty for large arrays/slices
   620  		value := reflect.ValueOf(dst)
   621  		if value.Kind() == reflect.Ptr {
   622  			value = value.Elem()
   623  		}
   624  
   625  		switch value.Kind() {
   626  		case reflect.Array, reflect.Slice:
   627  		default:
   628  			return fmt.Errorf("cannot assign %T to %T", src, dst)
   629  		}
   630  
   631  		if len(src.Elements) == 0 {
   632  			if value.Kind() == reflect.Slice {
   633  				value.Set(reflect.MakeSlice(value.Type(), 0, 0))
   634  				return nil
   635  			}
   636  		}
   637  
   638  		elementCount, err := src.assignToRecursive(value, 0, 0)
   639  		if err != nil {
   640  			return err
   641  		}
   642  		if elementCount != len(src.Elements) {
   643  			return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
   644  		}
   645  
   646  		return nil
   647  	case Null:
   648  		return NullAssignTo(dst)
   649  	}
   650  
   651  	return fmt.Errorf("cannot decode %#v into %T", src, dst)
   652  }
   653  
   654  func (src *Int4Array) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
   655  	switch kind := value.Kind(); kind {
   656  	case reflect.Array:
   657  		fallthrough
   658  	case reflect.Slice:
   659  		if len(src.Dimensions) == dimension {
   660  			break
   661  		}
   662  
   663  		length := int(src.Dimensions[dimension].Length)
   664  		if reflect.Array == kind {
   665  			typ := value.Type()
   666  			if typ.Len() != length {
   667  				return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
   668  			}
   669  			value.Set(reflect.New(typ).Elem())
   670  		} else {
   671  			value.Set(reflect.MakeSlice(value.Type(), length, length))
   672  		}
   673  
   674  		var err error
   675  		for i := 0; i < length; i++ {
   676  			index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
   677  			if err != nil {
   678  				return 0, err
   679  			}
   680  		}
   681  
   682  		return index, nil
   683  	}
   684  	if len(src.Dimensions) != dimension {
   685  		return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
   686  	}
   687  	if !value.CanAddr() {
   688  		return 0, fmt.Errorf("cannot assign all values from Int4Array")
   689  	}
   690  	addr := value.Addr()
   691  	if !addr.CanInterface() {
   692  		return 0, fmt.Errorf("cannot assign all values from Int4Array")
   693  	}
   694  	if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
   695  		return 0, err
   696  	}
   697  	index++
   698  	return index, nil
   699  }
   700  
   701  func (dst *Int4Array) DecodeText(ci *ConnInfo, src []byte) error {
   702  	if src == nil {
   703  		*dst = Int4Array{Status: Null}
   704  		return nil
   705  	}
   706  
   707  	uta, err := ParseUntypedTextArray(string(src))
   708  	if err != nil {
   709  		return err
   710  	}
   711  
   712  	var elements []Int4
   713  
   714  	if len(uta.Elements) > 0 {
   715  		elements = make([]Int4, len(uta.Elements))
   716  
   717  		for i, s := range uta.Elements {
   718  			var elem Int4
   719  			var elemSrc []byte
   720  			if s != "NULL" || uta.Quoted[i] {
   721  				elemSrc = []byte(s)
   722  			}
   723  			err = elem.DecodeText(ci, elemSrc)
   724  			if err != nil {
   725  				return err
   726  			}
   727  
   728  			elements[i] = elem
   729  		}
   730  	}
   731  
   732  	*dst = Int4Array{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
   733  
   734  	return nil
   735  }
   736  
   737  func (dst *Int4Array) DecodeBinary(ci *ConnInfo, src []byte) error {
   738  	if src == nil {
   739  		*dst = Int4Array{Status: Null}
   740  		return nil
   741  	}
   742  
   743  	var arrayHeader ArrayHeader
   744  	rp, err := arrayHeader.DecodeBinary(ci, src)
   745  	if err != nil {
   746  		return err
   747  	}
   748  
   749  	if len(arrayHeader.Dimensions) == 0 {
   750  		*dst = Int4Array{Dimensions: arrayHeader.Dimensions, Status: Present}
   751  		return nil
   752  	}
   753  
   754  	elementCount := arrayHeader.Dimensions[0].Length
   755  	for _, d := range arrayHeader.Dimensions[1:] {
   756  		elementCount *= d.Length
   757  	}
   758  
   759  	elements := make([]Int4, elementCount)
   760  
   761  	for i := range elements {
   762  		elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
   763  		rp += 4
   764  		var elemSrc []byte
   765  		if elemLen >= 0 {
   766  			elemSrc = src[rp : rp+elemLen]
   767  			rp += elemLen
   768  		}
   769  		err = elements[i].DecodeBinary(ci, elemSrc)
   770  		if err != nil {
   771  			return err
   772  		}
   773  	}
   774  
   775  	*dst = Int4Array{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
   776  	return nil
   777  }
   778  
   779  func (src Int4Array) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
   780  	switch src.Status {
   781  	case Null:
   782  		return nil, nil
   783  	case Undefined:
   784  		return nil, errUndefined
   785  	}
   786  
   787  	if len(src.Dimensions) == 0 {
   788  		return append(buf, '{', '}'), nil
   789  	}
   790  
   791  	buf = EncodeTextArrayDimensions(buf, src.Dimensions)
   792  
   793  	// dimElemCounts is the multiples of elements that each array lies on. For
   794  	// example, a single dimension array of length 4 would have a dimElemCounts of
   795  	// [4]. A multi-dimensional array of lengths [3,5,2] would have a
   796  	// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
   797  	// or '}'.
   798  	dimElemCounts := make([]int, len(src.Dimensions))
   799  	dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
   800  	for i := len(src.Dimensions) - 2; i > -1; i-- {
   801  		dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
   802  	}
   803  
   804  	inElemBuf := make([]byte, 0, 32)
   805  	for i, elem := range src.Elements {
   806  		if i > 0 {
   807  			buf = append(buf, ',')
   808  		}
   809  
   810  		for _, dec := range dimElemCounts {
   811  			if i%dec == 0 {
   812  				buf = append(buf, '{')
   813  			}
   814  		}
   815  
   816  		elemBuf, err := elem.EncodeText(ci, inElemBuf)
   817  		if err != nil {
   818  			return nil, err
   819  		}
   820  		if elemBuf == nil {
   821  			buf = append(buf, `NULL`...)
   822  		} else {
   823  			buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
   824  		}
   825  
   826  		for _, dec := range dimElemCounts {
   827  			if (i+1)%dec == 0 {
   828  				buf = append(buf, '}')
   829  			}
   830  		}
   831  	}
   832  
   833  	return buf, nil
   834  }
   835  
   836  func (src Int4Array) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
   837  	switch src.Status {
   838  	case Null:
   839  		return nil, nil
   840  	case Undefined:
   841  		return nil, errUndefined
   842  	}
   843  
   844  	arrayHeader := ArrayHeader{
   845  		Dimensions: src.Dimensions,
   846  	}
   847  
   848  	if dt, ok := ci.DataTypeForName("int4"); ok {
   849  		arrayHeader.ElementOID = int32(dt.OID)
   850  	} else {
   851  		return nil, fmt.Errorf("unable to find oid for type name %v", "int4")
   852  	}
   853  
   854  	for i := range src.Elements {
   855  		if src.Elements[i].Status == Null {
   856  			arrayHeader.ContainsNull = true
   857  			break
   858  		}
   859  	}
   860  
   861  	buf = arrayHeader.EncodeBinary(ci, buf)
   862  
   863  	for i := range src.Elements {
   864  		sp := len(buf)
   865  		buf = pgio.AppendInt32(buf, -1)
   866  
   867  		elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
   868  		if err != nil {
   869  			return nil, err
   870  		}
   871  		if elemBuf != nil {
   872  			buf = elemBuf
   873  			pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
   874  		}
   875  	}
   876  
   877  	return buf, nil
   878  }
   879  
   880  // Scan implements the database/sql Scanner interface.
   881  func (dst *Int4Array) Scan(src interface{}) error {
   882  	if src == nil {
   883  		return dst.DecodeText(nil, nil)
   884  	}
   885  
   886  	switch src := src.(type) {
   887  	case string:
   888  		return dst.DecodeText(nil, []byte(src))
   889  	case []byte:
   890  		srcCopy := make([]byte, len(src))
   891  		copy(srcCopy, src)
   892  		return dst.DecodeText(nil, srcCopy)
   893  	}
   894  
   895  	return fmt.Errorf("cannot scan %T", src)
   896  }
   897  
   898  // Value implements the database/sql/driver Valuer interface.
   899  func (src Int4Array) Value() (driver.Value, error) {
   900  	buf, err := src.EncodeText(nil, nil)
   901  	if err != nil {
   902  		return nil, err
   903  	}
   904  	if buf == nil {
   905  		return nil, nil
   906  	}
   907  
   908  	return string(buf), nil
   909  }
   910  

View as plain text