taler-mailbox

Service for asynchronous wallet-to-wallet payment messages
Log | Files | Refs | Submodules | README | LICENSE

array.go (20671B)


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