...

Source file src/github.com/lib/pq/array.go

Documentation: github.com/lib/pq

     1  package pq
     2  
     3  import (
     4  	"bytes"
     5  	"database/sql"
     6  	"database/sql/driver"
     7  	"encoding/hex"
     8  	"fmt"
     9  	"reflect"
    10  	"strconv"
    11  	"strings"
    12  )
    13  
    14  var typeByteSlice = reflect.TypeOf([]byte{})
    15  var typeDriverValuer = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
    16  var typeSQLScanner = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
    17  
    18  // Array returns the optimal driver.Valuer and sql.Scanner for an array or
    19  // slice of any dimension.
    20  //
    21  // For example:
    22  //  db.Query(`SELECT * FROM t WHERE id = ANY($1)`, pq.Array([]int{235, 401}))
    23  //
    24  //  var x []sql.NullInt64
    25  //  db.QueryRow(`SELECT ARRAY[235, 401]`).Scan(pq.Array(&x))
    26  //
    27  // Scanning multi-dimensional arrays is not supported.  Arrays where the lower
    28  // bound is not one (such as `[0:0]={1}') are not supported.
    29  func Array(a interface{}) interface {
    30  	driver.Valuer
    31  	sql.Scanner
    32  } {
    33  	switch a := a.(type) {
    34  	case []bool:
    35  		return (*BoolArray)(&a)
    36  	case []float64:
    37  		return (*Float64Array)(&a)
    38  	case []float32:
    39  		return (*Float32Array)(&a)
    40  	case []int64:
    41  		return (*Int64Array)(&a)
    42  	case []int32:
    43  		return (*Int32Array)(&a)
    44  	case []string:
    45  		return (*StringArray)(&a)
    46  	case [][]byte:
    47  		return (*ByteaArray)(&a)
    48  
    49  	case *[]bool:
    50  		return (*BoolArray)(a)
    51  	case *[]float64:
    52  		return (*Float64Array)(a)
    53  	case *[]float32:
    54  		return (*Float32Array)(a)
    55  	case *[]int64:
    56  		return (*Int64Array)(a)
    57  	case *[]int32:
    58  		return (*Int32Array)(a)
    59  	case *[]string:
    60  		return (*StringArray)(a)
    61  	case *[][]byte:
    62  		return (*ByteaArray)(a)
    63  	}
    64  
    65  	return GenericArray{a}
    66  }
    67  
    68  // ArrayDelimiter may be optionally implemented by driver.Valuer or sql.Scanner
    69  // to override the array delimiter used by GenericArray.
    70  type ArrayDelimiter interface {
    71  	// ArrayDelimiter returns the delimiter character(s) for this element's type.
    72  	ArrayDelimiter() string
    73  }
    74  
    75  // BoolArray represents a one-dimensional array of the PostgreSQL boolean type.
    76  type BoolArray []bool
    77  
    78  // Scan implements the sql.Scanner interface.
    79  func (a *BoolArray) Scan(src interface{}) error {
    80  	switch src := src.(type) {
    81  	case []byte:
    82  		return a.scanBytes(src)
    83  	case string:
    84  		return a.scanBytes([]byte(src))
    85  	case nil:
    86  		*a = nil
    87  		return nil
    88  	}
    89  
    90  	return fmt.Errorf("pq: cannot convert %T to BoolArray", src)
    91  }
    92  
    93  func (a *BoolArray) scanBytes(src []byte) error {
    94  	elems, err := scanLinearArray(src, []byte{','}, "BoolArray")
    95  	if err != nil {
    96  		return err
    97  	}
    98  	if *a != nil && len(elems) == 0 {
    99  		*a = (*a)[:0]
   100  	} else {
   101  		b := make(BoolArray, len(elems))
   102  		for i, v := range elems {
   103  			if len(v) != 1 {
   104  				return fmt.Errorf("pq: could not parse boolean array index %d: invalid boolean %q", i, v)
   105  			}
   106  			switch v[0] {
   107  			case 't':
   108  				b[i] = true
   109  			case 'f':
   110  				b[i] = false
   111  			default:
   112  				return fmt.Errorf("pq: could not parse boolean array index %d: invalid boolean %q", i, v)
   113  			}
   114  		}
   115  		*a = b
   116  	}
   117  	return nil
   118  }
   119  
   120  // Value implements the driver.Valuer interface.
   121  func (a BoolArray) Value() (driver.Value, error) {
   122  	if a == nil {
   123  		return nil, nil
   124  	}
   125  
   126  	if n := len(a); n > 0 {
   127  		// There will be exactly two curly brackets, N bytes of values,
   128  		// and N-1 bytes of delimiters.
   129  		b := make([]byte, 1+2*n)
   130  
   131  		for i := 0; i < n; i++ {
   132  			b[2*i] = ','
   133  			if a[i] {
   134  				b[1+2*i] = 't'
   135  			} else {
   136  				b[1+2*i] = 'f'
   137  			}
   138  		}
   139  
   140  		b[0] = '{'
   141  		b[2*n] = '}'
   142  
   143  		return string(b), nil
   144  	}
   145  
   146  	return "{}", nil
   147  }
   148  
   149  // ByteaArray represents a one-dimensional array of the PostgreSQL bytea type.
   150  type ByteaArray [][]byte
   151  
   152  // Scan implements the sql.Scanner interface.
   153  func (a *ByteaArray) Scan(src interface{}) error {
   154  	switch src := src.(type) {
   155  	case []byte:
   156  		return a.scanBytes(src)
   157  	case string:
   158  		return a.scanBytes([]byte(src))
   159  	case nil:
   160  		*a = nil
   161  		return nil
   162  	}
   163  
   164  	return fmt.Errorf("pq: cannot convert %T to ByteaArray", src)
   165  }
   166  
   167  func (a *ByteaArray) scanBytes(src []byte) error {
   168  	elems, err := scanLinearArray(src, []byte{','}, "ByteaArray")
   169  	if err != nil {
   170  		return err
   171  	}
   172  	if *a != nil && len(elems) == 0 {
   173  		*a = (*a)[:0]
   174  	} else {
   175  		b := make(ByteaArray, len(elems))
   176  		for i, v := range elems {
   177  			b[i], err = parseBytea(v)
   178  			if err != nil {
   179  				return fmt.Errorf("could not parse bytea array index %d: %s", i, err.Error())
   180  			}
   181  		}
   182  		*a = b
   183  	}
   184  	return nil
   185  }
   186  
   187  // Value implements the driver.Valuer interface. It uses the "hex" format which
   188  // is only supported on PostgreSQL 9.0 or newer.
   189  func (a ByteaArray) Value() (driver.Value, error) {
   190  	if a == nil {
   191  		return nil, nil
   192  	}
   193  
   194  	if n := len(a); n > 0 {
   195  		// There will be at least two curly brackets, 2*N bytes of quotes,
   196  		// 3*N bytes of hex formatting, and N-1 bytes of delimiters.
   197  		size := 1 + 6*n
   198  		for _, x := range a {
   199  			size += hex.EncodedLen(len(x))
   200  		}
   201  
   202  		b := make([]byte, size)
   203  
   204  		for i, s := 0, b; i < n; i++ {
   205  			o := copy(s, `,"\\x`)
   206  			o += hex.Encode(s[o:], a[i])
   207  			s[o] = '"'
   208  			s = s[o+1:]
   209  		}
   210  
   211  		b[0] = '{'
   212  		b[size-1] = '}'
   213  
   214  		return string(b), nil
   215  	}
   216  
   217  	return "{}", nil
   218  }
   219  
   220  // Float64Array represents a one-dimensional array of the PostgreSQL double
   221  // precision type.
   222  type Float64Array []float64
   223  
   224  // Scan implements the sql.Scanner interface.
   225  func (a *Float64Array) Scan(src interface{}) error {
   226  	switch src := src.(type) {
   227  	case []byte:
   228  		return a.scanBytes(src)
   229  	case string:
   230  		return a.scanBytes([]byte(src))
   231  	case nil:
   232  		*a = nil
   233  		return nil
   234  	}
   235  
   236  	return fmt.Errorf("pq: cannot convert %T to Float64Array", src)
   237  }
   238  
   239  func (a *Float64Array) scanBytes(src []byte) error {
   240  	elems, err := scanLinearArray(src, []byte{','}, "Float64Array")
   241  	if err != nil {
   242  		return err
   243  	}
   244  	if *a != nil && len(elems) == 0 {
   245  		*a = (*a)[:0]
   246  	} else {
   247  		b := make(Float64Array, len(elems))
   248  		for i, v := range elems {
   249  			if b[i], err = strconv.ParseFloat(string(v), 64); err != nil {
   250  				return fmt.Errorf("pq: parsing array element index %d: %v", i, err)
   251  			}
   252  		}
   253  		*a = b
   254  	}
   255  	return nil
   256  }
   257  
   258  // Value implements the driver.Valuer interface.
   259  func (a Float64Array) Value() (driver.Value, error) {
   260  	if a == nil {
   261  		return nil, nil
   262  	}
   263  
   264  	if n := len(a); n > 0 {
   265  		// There will be at least two curly brackets, N bytes of values,
   266  		// and N-1 bytes of delimiters.
   267  		b := make([]byte, 1, 1+2*n)
   268  		b[0] = '{'
   269  
   270  		b = strconv.AppendFloat(b, a[0], 'f', -1, 64)
   271  		for i := 1; i < n; i++ {
   272  			b = append(b, ',')
   273  			b = strconv.AppendFloat(b, a[i], 'f', -1, 64)
   274  		}
   275  
   276  		return string(append(b, '}')), nil
   277  	}
   278  
   279  	return "{}", nil
   280  }
   281  
   282  // Float32Array represents a one-dimensional array of the PostgreSQL double
   283  // precision type.
   284  type Float32Array []float32
   285  
   286  // Scan implements the sql.Scanner interface.
   287  func (a *Float32Array) Scan(src interface{}) error {
   288  	switch src := src.(type) {
   289  	case []byte:
   290  		return a.scanBytes(src)
   291  	case string:
   292  		return a.scanBytes([]byte(src))
   293  	case nil:
   294  		*a = nil
   295  		return nil
   296  	}
   297  
   298  	return fmt.Errorf("pq: cannot convert %T to Float32Array", src)
   299  }
   300  
   301  func (a *Float32Array) scanBytes(src []byte) error {
   302  	elems, err := scanLinearArray(src, []byte{','}, "Float32Array")
   303  	if err != nil {
   304  		return err
   305  	}
   306  	if *a != nil && len(elems) == 0 {
   307  		*a = (*a)[:0]
   308  	} else {
   309  		b := make(Float32Array, len(elems))
   310  		for i, v := range elems {
   311  			var x float64
   312  			if x, err = strconv.ParseFloat(string(v), 32); err != nil {
   313  				return fmt.Errorf("pq: parsing array element index %d: %v", i, err)
   314  			}
   315  			b[i] = float32(x)
   316  		}
   317  		*a = b
   318  	}
   319  	return nil
   320  }
   321  
   322  // Value implements the driver.Valuer interface.
   323  func (a Float32Array) Value() (driver.Value, error) {
   324  	if a == nil {
   325  		return nil, nil
   326  	}
   327  
   328  	if n := len(a); n > 0 {
   329  		// There will be at least two curly brackets, N bytes of values,
   330  		// and N-1 bytes of delimiters.
   331  		b := make([]byte, 1, 1+2*n)
   332  		b[0] = '{'
   333  
   334  		b = strconv.AppendFloat(b, float64(a[0]), 'f', -1, 32)
   335  		for i := 1; i < n; i++ {
   336  			b = append(b, ',')
   337  			b = strconv.AppendFloat(b, float64(a[i]), 'f', -1, 32)
   338  		}
   339  
   340  		return string(append(b, '}')), nil
   341  	}
   342  
   343  	return "{}", nil
   344  }
   345  
   346  // GenericArray implements the driver.Valuer and sql.Scanner interfaces for
   347  // an array or slice of any dimension.
   348  type GenericArray struct{ A interface{} }
   349  
   350  func (GenericArray) evaluateDestination(rt reflect.Type) (reflect.Type, func([]byte, reflect.Value) error, string) {
   351  	var assign func([]byte, reflect.Value) error
   352  	var del = ","
   353  
   354  	// TODO calculate the assign function for other types
   355  	// TODO repeat this section on the element type of arrays or slices (multidimensional)
   356  	{
   357  		if reflect.PtrTo(rt).Implements(typeSQLScanner) {
   358  			// dest is always addressable because it is an element of a slice.
   359  			assign = func(src []byte, dest reflect.Value) (err error) {
   360  				ss := dest.Addr().Interface().(sql.Scanner)
   361  				if src == nil {
   362  					err = ss.Scan(nil)
   363  				} else {
   364  					err = ss.Scan(src)
   365  				}
   366  				return
   367  			}
   368  			goto FoundType
   369  		}
   370  
   371  		assign = func([]byte, reflect.Value) error {
   372  			return fmt.Errorf("pq: scanning to %s is not implemented; only sql.Scanner", rt)
   373  		}
   374  	}
   375  
   376  FoundType:
   377  
   378  	if ad, ok := reflect.Zero(rt).Interface().(ArrayDelimiter); ok {
   379  		del = ad.ArrayDelimiter()
   380  	}
   381  
   382  	return rt, assign, del
   383  }
   384  
   385  // Scan implements the sql.Scanner interface.
   386  func (a GenericArray) Scan(src interface{}) error {
   387  	dpv := reflect.ValueOf(a.A)
   388  	switch {
   389  	case dpv.Kind() != reflect.Ptr:
   390  		return fmt.Errorf("pq: destination %T is not a pointer to array or slice", a.A)
   391  	case dpv.IsNil():
   392  		return fmt.Errorf("pq: destination %T is nil", a.A)
   393  	}
   394  
   395  	dv := dpv.Elem()
   396  	switch dv.Kind() {
   397  	case reflect.Slice:
   398  	case reflect.Array:
   399  	default:
   400  		return fmt.Errorf("pq: destination %T is not a pointer to array or slice", a.A)
   401  	}
   402  
   403  	switch src := src.(type) {
   404  	case []byte:
   405  		return a.scanBytes(src, dv)
   406  	case string:
   407  		return a.scanBytes([]byte(src), dv)
   408  	case nil:
   409  		if dv.Kind() == reflect.Slice {
   410  			dv.Set(reflect.Zero(dv.Type()))
   411  			return nil
   412  		}
   413  	}
   414  
   415  	return fmt.Errorf("pq: cannot convert %T to %s", src, dv.Type())
   416  }
   417  
   418  func (a GenericArray) scanBytes(src []byte, dv reflect.Value) error {
   419  	dtype, assign, del := a.evaluateDestination(dv.Type().Elem())
   420  	dims, elems, err := parseArray(src, []byte(del))
   421  	if err != nil {
   422  		return err
   423  	}
   424  
   425  	// TODO allow multidimensional
   426  
   427  	if len(dims) > 1 {
   428  		return fmt.Errorf("pq: scanning from multidimensional ARRAY%s is not implemented",
   429  			strings.Replace(fmt.Sprint(dims), " ", "][", -1))
   430  	}
   431  
   432  	// Treat a zero-dimensional array like an array with a single dimension of zero.
   433  	if len(dims) == 0 {
   434  		dims = append(dims, 0)
   435  	}
   436  
   437  	for i, rt := 0, dv.Type(); i < len(dims); i, rt = i+1, rt.Elem() {
   438  		switch rt.Kind() {
   439  		case reflect.Slice:
   440  		case reflect.Array:
   441  			if rt.Len() != dims[i] {
   442  				return fmt.Errorf("pq: cannot convert ARRAY%s to %s",
   443  					strings.Replace(fmt.Sprint(dims), " ", "][", -1), dv.Type())
   444  			}
   445  		default:
   446  			// TODO handle multidimensional
   447  		}
   448  	}
   449  
   450  	values := reflect.MakeSlice(reflect.SliceOf(dtype), len(elems), len(elems))
   451  	for i, e := range elems {
   452  		if err := assign(e, values.Index(i)); err != nil {
   453  			return fmt.Errorf("pq: parsing array element index %d: %v", i, err)
   454  		}
   455  	}
   456  
   457  	// TODO handle multidimensional
   458  
   459  	switch dv.Kind() {
   460  	case reflect.Slice:
   461  		dv.Set(values.Slice(0, dims[0]))
   462  	case reflect.Array:
   463  		for i := 0; i < dims[0]; i++ {
   464  			dv.Index(i).Set(values.Index(i))
   465  		}
   466  	}
   467  
   468  	return nil
   469  }
   470  
   471  // Value implements the driver.Valuer interface.
   472  func (a GenericArray) Value() (driver.Value, error) {
   473  	if a.A == nil {
   474  		return nil, nil
   475  	}
   476  
   477  	rv := reflect.ValueOf(a.A)
   478  
   479  	switch rv.Kind() {
   480  	case reflect.Slice:
   481  		if rv.IsNil() {
   482  			return nil, nil
   483  		}
   484  	case reflect.Array:
   485  	default:
   486  		return nil, fmt.Errorf("pq: Unable to convert %T to array", a.A)
   487  	}
   488  
   489  	if n := rv.Len(); n > 0 {
   490  		// There will be at least two curly brackets, N bytes of values,
   491  		// and N-1 bytes of delimiters.
   492  		b := make([]byte, 0, 1+2*n)
   493  
   494  		b, _, err := appendArray(b, rv, n)
   495  		return string(b), err
   496  	}
   497  
   498  	return "{}", nil
   499  }
   500  
   501  // Int64Array represents a one-dimensional array of the PostgreSQL integer types.
   502  type Int64Array []int64
   503  
   504  // Scan implements the sql.Scanner interface.
   505  func (a *Int64Array) Scan(src interface{}) error {
   506  	switch src := src.(type) {
   507  	case []byte:
   508  		return a.scanBytes(src)
   509  	case string:
   510  		return a.scanBytes([]byte(src))
   511  	case nil:
   512  		*a = nil
   513  		return nil
   514  	}
   515  
   516  	return fmt.Errorf("pq: cannot convert %T to Int64Array", src)
   517  }
   518  
   519  func (a *Int64Array) scanBytes(src []byte) error {
   520  	elems, err := scanLinearArray(src, []byte{','}, "Int64Array")
   521  	if err != nil {
   522  		return err
   523  	}
   524  	if *a != nil && len(elems) == 0 {
   525  		*a = (*a)[:0]
   526  	} else {
   527  		b := make(Int64Array, len(elems))
   528  		for i, v := range elems {
   529  			if b[i], err = strconv.ParseInt(string(v), 10, 64); err != nil {
   530  				return fmt.Errorf("pq: parsing array element index %d: %v", i, err)
   531  			}
   532  		}
   533  		*a = b
   534  	}
   535  	return nil
   536  }
   537  
   538  // Value implements the driver.Valuer interface.
   539  func (a Int64Array) Value() (driver.Value, error) {
   540  	if a == nil {
   541  		return nil, nil
   542  	}
   543  
   544  	if n := len(a); n > 0 {
   545  		// There will be at least two curly brackets, N bytes of values,
   546  		// and N-1 bytes of delimiters.
   547  		b := make([]byte, 1, 1+2*n)
   548  		b[0] = '{'
   549  
   550  		b = strconv.AppendInt(b, a[0], 10)
   551  		for i := 1; i < n; i++ {
   552  			b = append(b, ',')
   553  			b = strconv.AppendInt(b, a[i], 10)
   554  		}
   555  
   556  		return string(append(b, '}')), nil
   557  	}
   558  
   559  	return "{}", nil
   560  }
   561  
   562  // Int32Array represents a one-dimensional array of the PostgreSQL integer types.
   563  type Int32Array []int32
   564  
   565  // Scan implements the sql.Scanner interface.
   566  func (a *Int32Array) Scan(src interface{}) error {
   567  	switch src := src.(type) {
   568  	case []byte:
   569  		return a.scanBytes(src)
   570  	case string:
   571  		return a.scanBytes([]byte(src))
   572  	case nil:
   573  		*a = nil
   574  		return nil
   575  	}
   576  
   577  	return fmt.Errorf("pq: cannot convert %T to Int32Array", src)
   578  }
   579  
   580  func (a *Int32Array) scanBytes(src []byte) error {
   581  	elems, err := scanLinearArray(src, []byte{','}, "Int32Array")
   582  	if err != nil {
   583  		return err
   584  	}
   585  	if *a != nil && len(elems) == 0 {
   586  		*a = (*a)[:0]
   587  	} else {
   588  		b := make(Int32Array, len(elems))
   589  		for i, v := range elems {
   590  			x, err := strconv.ParseInt(string(v), 10, 32)
   591  			if err != nil {
   592  				return fmt.Errorf("pq: parsing array element index %d: %v", i, err)
   593  			}
   594  			b[i] = int32(x)
   595  		}
   596  		*a = b
   597  	}
   598  	return nil
   599  }
   600  
   601  // Value implements the driver.Valuer interface.
   602  func (a Int32Array) Value() (driver.Value, error) {
   603  	if a == nil {
   604  		return nil, nil
   605  	}
   606  
   607  	if n := len(a); n > 0 {
   608  		// There will be at least two curly brackets, N bytes of values,
   609  		// and N-1 bytes of delimiters.
   610  		b := make([]byte, 1, 1+2*n)
   611  		b[0] = '{'
   612  
   613  		b = strconv.AppendInt(b, int64(a[0]), 10)
   614  		for i := 1; i < n; i++ {
   615  			b = append(b, ',')
   616  			b = strconv.AppendInt(b, int64(a[i]), 10)
   617  		}
   618  
   619  		return string(append(b, '}')), nil
   620  	}
   621  
   622  	return "{}", nil
   623  }
   624  
   625  // StringArray represents a one-dimensional array of the PostgreSQL character types.
   626  type StringArray []string
   627  
   628  // Scan implements the sql.Scanner interface.
   629  func (a *StringArray) Scan(src interface{}) error {
   630  	switch src := src.(type) {
   631  	case []byte:
   632  		return a.scanBytes(src)
   633  	case string:
   634  		return a.scanBytes([]byte(src))
   635  	case nil:
   636  		*a = nil
   637  		return nil
   638  	}
   639  
   640  	return fmt.Errorf("pq: cannot convert %T to StringArray", src)
   641  }
   642  
   643  func (a *StringArray) scanBytes(src []byte) error {
   644  	elems, err := scanLinearArray(src, []byte{','}, "StringArray")
   645  	if err != nil {
   646  		return err
   647  	}
   648  	if *a != nil && len(elems) == 0 {
   649  		*a = (*a)[:0]
   650  	} else {
   651  		b := make(StringArray, len(elems))
   652  		for i, v := range elems {
   653  			if b[i] = string(v); v == nil {
   654  				return fmt.Errorf("pq: parsing array element index %d: cannot convert nil to string", i)
   655  			}
   656  		}
   657  		*a = b
   658  	}
   659  	return nil
   660  }
   661  
   662  // Value implements the driver.Valuer interface.
   663  func (a StringArray) Value() (driver.Value, error) {
   664  	if a == nil {
   665  		return nil, nil
   666  	}
   667  
   668  	if n := len(a); n > 0 {
   669  		// There will be at least two curly brackets, 2*N bytes of quotes,
   670  		// and N-1 bytes of delimiters.
   671  		b := make([]byte, 1, 1+3*n)
   672  		b[0] = '{'
   673  
   674  		b = appendArrayQuotedBytes(b, []byte(a[0]))
   675  		for i := 1; i < n; i++ {
   676  			b = append(b, ',')
   677  			b = appendArrayQuotedBytes(b, []byte(a[i]))
   678  		}
   679  
   680  		return string(append(b, '}')), nil
   681  	}
   682  
   683  	return "{}", nil
   684  }
   685  
   686  // appendArray appends rv to the buffer, returning the extended buffer and
   687  // the delimiter used between elements.
   688  //
   689  // It panics when n <= 0 or rv's Kind is not reflect.Array nor reflect.Slice.
   690  func appendArray(b []byte, rv reflect.Value, n int) ([]byte, string, error) {
   691  	var del string
   692  	var err error
   693  
   694  	b = append(b, '{')
   695  
   696  	if b, del, err = appendArrayElement(b, rv.Index(0)); err != nil {
   697  		return b, del, err
   698  	}
   699  
   700  	for i := 1; i < n; i++ {
   701  		b = append(b, del...)
   702  		if b, del, err = appendArrayElement(b, rv.Index(i)); err != nil {
   703  			return b, del, err
   704  		}
   705  	}
   706  
   707  	return append(b, '}'), del, nil
   708  }
   709  
   710  // appendArrayElement appends rv to the buffer, returning the extended buffer
   711  // and the delimiter to use before the next element.
   712  //
   713  // When rv's Kind is neither reflect.Array nor reflect.Slice, it is converted
   714  // using driver.DefaultParameterConverter and the resulting []byte or string
   715  // is double-quoted.
   716  //
   717  // See http://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-IO
   718  func appendArrayElement(b []byte, rv reflect.Value) ([]byte, string, error) {
   719  	if k := rv.Kind(); k == reflect.Array || k == reflect.Slice {
   720  		if t := rv.Type(); t != typeByteSlice && !t.Implements(typeDriverValuer) {
   721  			if n := rv.Len(); n > 0 {
   722  				return appendArray(b, rv, n)
   723  			}
   724  
   725  			return b, "", nil
   726  		}
   727  	}
   728  
   729  	var del = ","
   730  	var err error
   731  	var iv interface{} = rv.Interface()
   732  
   733  	if ad, ok := iv.(ArrayDelimiter); ok {
   734  		del = ad.ArrayDelimiter()
   735  	}
   736  
   737  	if iv, err = driver.DefaultParameterConverter.ConvertValue(iv); err != nil {
   738  		return b, del, err
   739  	}
   740  
   741  	switch v := iv.(type) {
   742  	case nil:
   743  		return append(b, "NULL"...), del, nil
   744  	case []byte:
   745  		return appendArrayQuotedBytes(b, v), del, nil
   746  	case string:
   747  		return appendArrayQuotedBytes(b, []byte(v)), del, nil
   748  	}
   749  
   750  	b, err = appendValue(b, iv)
   751  	return b, del, err
   752  }
   753  
   754  func appendArrayQuotedBytes(b, v []byte) []byte {
   755  	b = append(b, '"')
   756  	for {
   757  		i := bytes.IndexAny(v, `"\`)
   758  		if i < 0 {
   759  			b = append(b, v...)
   760  			break
   761  		}
   762  		if i > 0 {
   763  			b = append(b, v[:i]...)
   764  		}
   765  		b = append(b, '\\', v[i])
   766  		v = v[i+1:]
   767  	}
   768  	return append(b, '"')
   769  }
   770  
   771  func appendValue(b []byte, v driver.Value) ([]byte, error) {
   772  	return append(b, encode(nil, v, 0)...), nil
   773  }
   774  
   775  // parseArray extracts the dimensions and elements of an array represented in
   776  // text format. Only representations emitted by the backend are supported.
   777  // Notably, whitespace around brackets and delimiters is significant, and NULL
   778  // is case-sensitive.
   779  //
   780  // See http://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-IO
   781  func parseArray(src, del []byte) (dims []int, elems [][]byte, err error) {
   782  	var depth, i int
   783  
   784  	if len(src) < 1 || src[0] != '{' {
   785  		return nil, nil, fmt.Errorf("pq: unable to parse array; expected %q at offset %d", '{', 0)
   786  	}
   787  
   788  Open:
   789  	for i < len(src) {
   790  		switch src[i] {
   791  		case '{':
   792  			depth++
   793  			i++
   794  		case '}':
   795  			elems = make([][]byte, 0)
   796  			goto Close
   797  		default:
   798  			break Open
   799  		}
   800  	}
   801  	dims = make([]int, i)
   802  
   803  Element:
   804  	for i < len(src) {
   805  		switch src[i] {
   806  		case '{':
   807  			if depth == len(dims) {
   808  				break Element
   809  			}
   810  			depth++
   811  			dims[depth-1] = 0
   812  			i++
   813  		case '"':
   814  			var elem = []byte{}
   815  			var escape bool
   816  			for i++; i < len(src); i++ {
   817  				if escape {
   818  					elem = append(elem, src[i])
   819  					escape = false
   820  				} else {
   821  					switch src[i] {
   822  					default:
   823  						elem = append(elem, src[i])
   824  					case '\\':
   825  						escape = true
   826  					case '"':
   827  						elems = append(elems, elem)
   828  						i++
   829  						break Element
   830  					}
   831  				}
   832  			}
   833  		default:
   834  			for start := i; i < len(src); i++ {
   835  				if bytes.HasPrefix(src[i:], del) || src[i] == '}' {
   836  					elem := src[start:i]
   837  					if len(elem) == 0 {
   838  						return nil, nil, fmt.Errorf("pq: unable to parse array; unexpected %q at offset %d", src[i], i)
   839  					}
   840  					if bytes.Equal(elem, []byte("NULL")) {
   841  						elem = nil
   842  					}
   843  					elems = append(elems, elem)
   844  					break Element
   845  				}
   846  			}
   847  		}
   848  	}
   849  
   850  	for i < len(src) {
   851  		if bytes.HasPrefix(src[i:], del) && depth > 0 {
   852  			dims[depth-1]++
   853  			i += len(del)
   854  			goto Element
   855  		} else if src[i] == '}' && depth > 0 {
   856  			dims[depth-1]++
   857  			depth--
   858  			i++
   859  		} else {
   860  			return nil, nil, fmt.Errorf("pq: unable to parse array; unexpected %q at offset %d", src[i], i)
   861  		}
   862  	}
   863  
   864  Close:
   865  	for i < len(src) {
   866  		if src[i] == '}' && depth > 0 {
   867  			depth--
   868  			i++
   869  		} else {
   870  			return nil, nil, fmt.Errorf("pq: unable to parse array; unexpected %q at offset %d", src[i], i)
   871  		}
   872  	}
   873  	if depth > 0 {
   874  		err = fmt.Errorf("pq: unable to parse array; expected %q at offset %d", '}', i)
   875  	}
   876  	if err == nil {
   877  		for _, d := range dims {
   878  			if (len(elems) % d) != 0 {
   879  				err = fmt.Errorf("pq: multidimensional arrays must have elements with matching dimensions")
   880  			}
   881  		}
   882  	}
   883  	return
   884  }
   885  
   886  func scanLinearArray(src, del []byte, typ string) (elems [][]byte, err error) {
   887  	dims, elems, err := parseArray(src, del)
   888  	if err != nil {
   889  		return nil, err
   890  	}
   891  	if len(dims) > 1 {
   892  		return nil, fmt.Errorf("pq: cannot convert ARRAY%s to %s", strings.Replace(fmt.Sprint(dims), " ", "][", -1), typ)
   893  	}
   894  	return elems, err
   895  }
   896  

View as plain text