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 }