1/* 2Copyright 2017 Google LLC 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package spanner 18 19import ( 20 "encoding/base64" 21 "fmt" 22 "math" 23 "reflect" 24 "strconv" 25 "time" 26 27 "cloud.google.com/go/civil" 28 "cloud.google.com/go/internal/fields" 29 proto "github.com/golang/protobuf/proto" 30 proto3 "github.com/golang/protobuf/ptypes/struct" 31 sppb "google.golang.org/genproto/googleapis/spanner/v1" 32 "google.golang.org/grpc/codes" 33) 34 35const commitTimestampPlaceholderString = "spanner.commit_timestamp()" 36 37var ( 38 // CommitTimestamp is a special value used to tell Cloud Spanner 39 // to insert the commit timestamp of the transaction into a column. 40 // It can be used in a Mutation, or directly used in 41 // InsertStruct or InsertMap. See ExampleCommitTimestamp. 42 // This is just a placeholder and the actual value stored in this 43 // variable has no meaning. 44 CommitTimestamp = commitTimestamp 45 commitTimestamp = time.Unix(0, 0).In(time.FixedZone("CommitTimestamp placeholder", 0xDB)) 46) 47 48// NullInt64 represents a Cloud Spanner INT64 that may be NULL. 49type NullInt64 struct { 50 Int64 int64 51 Valid bool // Valid is true if Int64 is not NULL. 52} 53 54// String implements Stringer.String for NullInt64 55func (n NullInt64) String() string { 56 if !n.Valid { 57 return fmt.Sprintf("%v", "<null>") 58 } 59 return fmt.Sprintf("%v", n.Int64) 60} 61 62// NullString represents a Cloud Spanner STRING that may be NULL. 63type NullString struct { 64 StringVal string 65 Valid bool // Valid is true if StringVal is not NULL. 66} 67 68// String implements Stringer.String for NullString 69func (n NullString) String() string { 70 if !n.Valid { 71 return fmt.Sprintf("%v", "<null>") 72 } 73 return fmt.Sprintf("%q", n.StringVal) 74} 75 76// NullFloat64 represents a Cloud Spanner FLOAT64 that may be NULL. 77type NullFloat64 struct { 78 Float64 float64 79 Valid bool // Valid is true if Float64 is not NULL. 80} 81 82// Cloud Spanner STRUCT (aka STRUCT) values (https://cloud.google.com/spanner/docs/data-types#struct-type) 83// can be represented by a Go struct value. 84// The spanner.StructType of such values is built from the field types and field tag information 85// of the Go struct. If a field in the struct type definition has a "spanner:<field_name>" tag, 86// then the value of the "spanner" key in the tag is used as the name for that field in the 87// built spanner.StructType, otherwise the field name in the struct definition is used. To specify a 88// field with an empty field name in a Cloud Spanner STRUCT type, use the `spanner:""` tag 89// annotation against the corresponding field in the Go struct's type definition. 90// 91// A STRUCT value can contain STRUCT-typed and Array-of-STRUCT typed fields and these can be 92// specified using named struct-typed and []struct-typed fields inside a Go struct. However, 93// embedded struct fields are not allowed. Unexported struct fields are ignored. 94// 95// NULL STRUCT values in Cloud Spanner are typed. A nil pointer to a Go struct value can be used to 96// specify a NULL STRUCT value of the corresponding spanner.StructType. Nil and empty slices of a 97// Go STRUCT type can be used to specify NULL and empty array values respectively of the 98// corresponding spanner.StructType. A slice of pointers to a Go struct type can be used to specify 99// an array of NULL-able STRUCT values. 100 101// String implements Stringer.String for NullFloat64 102func (n NullFloat64) String() string { 103 if !n.Valid { 104 return fmt.Sprintf("%v", "<null>") 105 } 106 return fmt.Sprintf("%v", n.Float64) 107} 108 109// NullBool represents a Cloud Spanner BOOL that may be NULL. 110type NullBool struct { 111 Bool bool 112 Valid bool // Valid is true if Bool is not NULL. 113} 114 115// String implements Stringer.String for NullBool 116func (n NullBool) String() string { 117 if !n.Valid { 118 return fmt.Sprintf("%v", "<null>") 119 } 120 return fmt.Sprintf("%v", n.Bool) 121} 122 123// NullTime represents a Cloud Spanner TIMESTAMP that may be null. 124type NullTime struct { 125 Time time.Time 126 Valid bool // Valid is true if Time is not NULL. 127} 128 129// String implements Stringer.String for NullTime 130func (n NullTime) String() string { 131 if !n.Valid { 132 return "<null>" 133 } 134 return fmt.Sprintf("%q", n.Time.Format(time.RFC3339Nano)) 135} 136 137// NullDate represents a Cloud Spanner DATE that may be null. 138type NullDate struct { 139 Date civil.Date 140 Valid bool // Valid is true if Date is not NULL. 141} 142 143// String implements Stringer.String for NullDate 144func (n NullDate) String() string { 145 if !n.Valid { 146 return "<null>" 147 } 148 return fmt.Sprintf("%q", n.Date) 149} 150 151// NullRow represents a Cloud Spanner STRUCT that may be NULL. 152// See also the document for Row. 153// Note that NullRow is not a valid Cloud Spanner column Type. 154type NullRow struct { 155 Row Row 156 Valid bool // Valid is true if Row is not NULL. 157} 158 159// GenericColumnValue represents the generic encoded value and type of the 160// column. See google.spanner.v1.ResultSet proto for details. This can be 161// useful for proxying query results when the result types are not known in 162// advance. 163// 164// If you populate a GenericColumnValue from a row using Row.Column or related 165// methods, do not modify the contents of Type and Value. 166type GenericColumnValue struct { 167 Type *sppb.Type 168 Value *proto3.Value 169} 170 171// Decode decodes a GenericColumnValue. The ptr argument should be a pointer 172// to a Go value that can accept v. 173func (v GenericColumnValue) Decode(ptr interface{}) error { 174 return decodeValue(v.Value, v.Type, ptr) 175} 176 177// NewGenericColumnValue creates a GenericColumnValue from Go value that is 178// valid for Cloud Spanner. 179func newGenericColumnValue(v interface{}) (*GenericColumnValue, error) { 180 value, typ, err := encodeValue(v) 181 if err != nil { 182 return nil, err 183 } 184 return &GenericColumnValue{Value: value, Type: typ}, nil 185} 186 187// errTypeMismatch returns error for destination not having a compatible type 188// with source Cloud Spanner type. 189func errTypeMismatch(srcCode, elCode sppb.TypeCode, dst interface{}) error { 190 s := srcCode.String() 191 if srcCode == sppb.TypeCode_ARRAY { 192 s = fmt.Sprintf("%v[%v]", srcCode, elCode) 193 } 194 return spannerErrorf(codes.InvalidArgument, "type %T cannot be used for decoding %s", dst, s) 195} 196 197// errNilSpannerType returns error for nil Cloud Spanner type in decoding. 198func errNilSpannerType() error { 199 return spannerErrorf(codes.FailedPrecondition, "unexpected nil Cloud Spanner data type in decoding") 200} 201 202// errNilSrc returns error for decoding from nil proto value. 203func errNilSrc() error { 204 return spannerErrorf(codes.FailedPrecondition, "unexpected nil Cloud Spanner value in decoding") 205} 206 207// errNilDst returns error for decoding into nil interface{}. 208func errNilDst(dst interface{}) error { 209 return spannerErrorf(codes.InvalidArgument, "cannot decode into nil type %T", dst) 210} 211 212// errNilArrElemType returns error for input Cloud Spanner data type being a array but without a 213// non-nil array element type. 214func errNilArrElemType(t *sppb.Type) error { 215 return spannerErrorf(codes.FailedPrecondition, "array type %v is with nil array element type", t) 216} 217 218func errUnsupportedEmbeddedStructFields(fname string) error { 219 return spannerErrorf(codes.InvalidArgument, "Embedded field: %s. Embedded and anonymous fields are not allowed "+ 220 "when converting Go structs to Cloud Spanner STRUCT values. To create a STRUCT value with an "+ 221 "unnamed field, use a `spanner:\"\"` field tag.", fname) 222} 223 224// errDstNotForNull returns error for decoding a SQL NULL value into a destination which doesn't 225// support NULL values. 226func errDstNotForNull(dst interface{}) error { 227 return spannerErrorf(codes.InvalidArgument, "destination %T cannot support NULL SQL values", dst) 228} 229 230// errBadEncoding returns error for decoding wrongly encoded types. 231func errBadEncoding(v *proto3.Value, err error) error { 232 return spannerErrorf(codes.FailedPrecondition, "%v wasn't correctly encoded: <%v>", v, err) 233} 234 235func parseNullTime(v *proto3.Value, p *NullTime, code sppb.TypeCode, isNull bool) error { 236 if p == nil { 237 return errNilDst(p) 238 } 239 if code != sppb.TypeCode_TIMESTAMP { 240 return errTypeMismatch(code, sppb.TypeCode_TYPE_CODE_UNSPECIFIED, p) 241 } 242 if isNull { 243 *p = NullTime{} 244 return nil 245 } 246 x, err := getStringValue(v) 247 if err != nil { 248 return err 249 } 250 y, err := time.Parse(time.RFC3339Nano, x) 251 if err != nil { 252 return errBadEncoding(v, err) 253 } 254 p.Valid = true 255 p.Time = y 256 return nil 257} 258 259// decodeValue decodes a protobuf Value into a pointer to a Go value, as 260// specified by sppb.Type. 261func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}) error { 262 if v == nil { 263 return errNilSrc() 264 } 265 if t == nil { 266 return errNilSpannerType() 267 } 268 code := t.Code 269 acode := sppb.TypeCode_TYPE_CODE_UNSPECIFIED 270 if code == sppb.TypeCode_ARRAY { 271 if t.ArrayElementType == nil { 272 return errNilArrElemType(t) 273 } 274 acode = t.ArrayElementType.Code 275 } 276 _, isNull := v.Kind.(*proto3.Value_NullValue) 277 278 // Do the decoding based on the type of ptr. 279 switch p := ptr.(type) { 280 case nil: 281 return errNilDst(nil) 282 case *string: 283 if p == nil { 284 return errNilDst(p) 285 } 286 if code != sppb.TypeCode_STRING { 287 return errTypeMismatch(code, acode, ptr) 288 } 289 if isNull { 290 return errDstNotForNull(ptr) 291 } 292 x, err := getStringValue(v) 293 if err != nil { 294 return err 295 } 296 *p = x 297 case *NullString: 298 if p == nil { 299 return errNilDst(p) 300 } 301 if code != sppb.TypeCode_STRING { 302 return errTypeMismatch(code, acode, ptr) 303 } 304 if isNull { 305 *p = NullString{} 306 break 307 } 308 x, err := getStringValue(v) 309 if err != nil { 310 return err 311 } 312 p.Valid = true 313 p.StringVal = x 314 case *[]NullString: 315 if p == nil { 316 return errNilDst(p) 317 } 318 if acode != sppb.TypeCode_STRING { 319 return errTypeMismatch(code, acode, ptr) 320 } 321 if isNull { 322 *p = nil 323 break 324 } 325 x, err := getListValue(v) 326 if err != nil { 327 return err 328 } 329 y, err := decodeNullStringArray(x) 330 if err != nil { 331 return err 332 } 333 *p = y 334 case *[]string: 335 if p == nil { 336 return errNilDst(p) 337 } 338 if acode != sppb.TypeCode_STRING { 339 return errTypeMismatch(code, acode, ptr) 340 } 341 if isNull { 342 *p = nil 343 break 344 } 345 x, err := getListValue(v) 346 if err != nil { 347 return err 348 } 349 y, err := decodeStringArray(x) 350 if err != nil { 351 return err 352 } 353 *p = y 354 case *[]byte: 355 if p == nil { 356 return errNilDst(p) 357 } 358 if code != sppb.TypeCode_BYTES { 359 return errTypeMismatch(code, acode, ptr) 360 } 361 if isNull { 362 *p = nil 363 break 364 } 365 x, err := getStringValue(v) 366 if err != nil { 367 return err 368 } 369 y, err := base64.StdEncoding.DecodeString(x) 370 if err != nil { 371 return errBadEncoding(v, err) 372 } 373 *p = y 374 case *[][]byte: 375 if p == nil { 376 return errNilDst(p) 377 } 378 if acode != sppb.TypeCode_BYTES { 379 return errTypeMismatch(code, acode, ptr) 380 } 381 if isNull { 382 *p = nil 383 break 384 } 385 x, err := getListValue(v) 386 if err != nil { 387 return err 388 } 389 y, err := decodeByteArray(x) 390 if err != nil { 391 return err 392 } 393 *p = y 394 case *int64: 395 if p == nil { 396 return errNilDst(p) 397 } 398 if code != sppb.TypeCode_INT64 { 399 return errTypeMismatch(code, acode, ptr) 400 } 401 if isNull { 402 return errDstNotForNull(ptr) 403 } 404 x, err := getStringValue(v) 405 if err != nil { 406 return err 407 } 408 y, err := strconv.ParseInt(x, 10, 64) 409 if err != nil { 410 return errBadEncoding(v, err) 411 } 412 *p = y 413 case *NullInt64: 414 if p == nil { 415 return errNilDst(p) 416 } 417 if code != sppb.TypeCode_INT64 { 418 return errTypeMismatch(code, acode, ptr) 419 } 420 if isNull { 421 *p = NullInt64{} 422 break 423 } 424 x, err := getStringValue(v) 425 if err != nil { 426 return err 427 } 428 y, err := strconv.ParseInt(x, 10, 64) 429 if err != nil { 430 return errBadEncoding(v, err) 431 } 432 p.Valid = true 433 p.Int64 = y 434 case *[]NullInt64: 435 if p == nil { 436 return errNilDst(p) 437 } 438 if acode != sppb.TypeCode_INT64 { 439 return errTypeMismatch(code, acode, ptr) 440 } 441 if isNull { 442 *p = nil 443 break 444 } 445 x, err := getListValue(v) 446 if err != nil { 447 return err 448 } 449 y, err := decodeNullInt64Array(x) 450 if err != nil { 451 return err 452 } 453 *p = y 454 case *[]int64: 455 if p == nil { 456 return errNilDst(p) 457 } 458 if acode != sppb.TypeCode_INT64 { 459 return errTypeMismatch(code, acode, ptr) 460 } 461 if isNull { 462 *p = nil 463 break 464 } 465 x, err := getListValue(v) 466 if err != nil { 467 return err 468 } 469 y, err := decodeInt64Array(x) 470 if err != nil { 471 return err 472 } 473 *p = y 474 case *bool: 475 if p == nil { 476 return errNilDst(p) 477 } 478 if code != sppb.TypeCode_BOOL { 479 return errTypeMismatch(code, acode, ptr) 480 } 481 if isNull { 482 return errDstNotForNull(ptr) 483 } 484 x, err := getBoolValue(v) 485 if err != nil { 486 return err 487 } 488 *p = x 489 case *NullBool: 490 if p == nil { 491 return errNilDst(p) 492 } 493 if code != sppb.TypeCode_BOOL { 494 return errTypeMismatch(code, acode, ptr) 495 } 496 if isNull { 497 *p = NullBool{} 498 break 499 } 500 x, err := getBoolValue(v) 501 if err != nil { 502 return err 503 } 504 p.Valid = true 505 p.Bool = x 506 case *[]NullBool: 507 if p == nil { 508 return errNilDst(p) 509 } 510 if acode != sppb.TypeCode_BOOL { 511 return errTypeMismatch(code, acode, ptr) 512 } 513 if isNull { 514 *p = nil 515 break 516 } 517 x, err := getListValue(v) 518 if err != nil { 519 return err 520 } 521 y, err := decodeNullBoolArray(x) 522 if err != nil { 523 return err 524 } 525 *p = y 526 case *[]bool: 527 if p == nil { 528 return errNilDst(p) 529 } 530 if acode != sppb.TypeCode_BOOL { 531 return errTypeMismatch(code, acode, ptr) 532 } 533 if isNull { 534 *p = nil 535 break 536 } 537 x, err := getListValue(v) 538 if err != nil { 539 return err 540 } 541 y, err := decodeBoolArray(x) 542 if err != nil { 543 return err 544 } 545 *p = y 546 case *float64: 547 if p == nil { 548 return errNilDst(p) 549 } 550 if code != sppb.TypeCode_FLOAT64 { 551 return errTypeMismatch(code, acode, ptr) 552 } 553 if isNull { 554 return errDstNotForNull(ptr) 555 } 556 x, err := getFloat64Value(v) 557 if err != nil { 558 return err 559 } 560 *p = x 561 case *NullFloat64: 562 if p == nil { 563 return errNilDst(p) 564 } 565 if code != sppb.TypeCode_FLOAT64 { 566 return errTypeMismatch(code, acode, ptr) 567 } 568 if isNull { 569 *p = NullFloat64{} 570 break 571 } 572 x, err := getFloat64Value(v) 573 if err != nil { 574 return err 575 } 576 p.Valid = true 577 p.Float64 = x 578 case *[]NullFloat64: 579 if p == nil { 580 return errNilDst(p) 581 } 582 if acode != sppb.TypeCode_FLOAT64 { 583 return errTypeMismatch(code, acode, ptr) 584 } 585 if isNull { 586 *p = nil 587 break 588 } 589 x, err := getListValue(v) 590 if err != nil { 591 return err 592 } 593 y, err := decodeNullFloat64Array(x) 594 if err != nil { 595 return err 596 } 597 *p = y 598 case *[]float64: 599 if p == nil { 600 return errNilDst(p) 601 } 602 if acode != sppb.TypeCode_FLOAT64 { 603 return errTypeMismatch(code, acode, ptr) 604 } 605 if isNull { 606 *p = nil 607 break 608 } 609 x, err := getListValue(v) 610 if err != nil { 611 return err 612 } 613 y, err := decodeFloat64Array(x) 614 if err != nil { 615 return err 616 } 617 *p = y 618 case *time.Time: 619 var nt NullTime 620 if isNull { 621 return errDstNotForNull(ptr) 622 } 623 err := parseNullTime(v, &nt, code, isNull) 624 if err != nil { 625 return nil 626 } 627 *p = nt.Time 628 case *NullTime: 629 err := parseNullTime(v, p, code, isNull) 630 if err != nil { 631 return err 632 } 633 case *[]NullTime: 634 if p == nil { 635 return errNilDst(p) 636 } 637 if acode != sppb.TypeCode_TIMESTAMP { 638 return errTypeMismatch(code, acode, ptr) 639 } 640 if isNull { 641 *p = nil 642 break 643 } 644 x, err := getListValue(v) 645 if err != nil { 646 return err 647 } 648 y, err := decodeNullTimeArray(x) 649 if err != nil { 650 return err 651 } 652 *p = y 653 case *[]time.Time: 654 if p == nil { 655 return errNilDst(p) 656 } 657 if acode != sppb.TypeCode_TIMESTAMP { 658 return errTypeMismatch(code, acode, ptr) 659 } 660 if isNull { 661 *p = nil 662 break 663 } 664 x, err := getListValue(v) 665 if err != nil { 666 return err 667 } 668 y, err := decodeTimeArray(x) 669 if err != nil { 670 return err 671 } 672 *p = y 673 case *civil.Date: 674 if p == nil { 675 return errNilDst(p) 676 } 677 if code != sppb.TypeCode_DATE { 678 return errTypeMismatch(code, acode, ptr) 679 } 680 if isNull { 681 return errDstNotForNull(ptr) 682 } 683 x, err := getStringValue(v) 684 if err != nil { 685 return err 686 } 687 y, err := civil.ParseDate(x) 688 if err != nil { 689 return errBadEncoding(v, err) 690 } 691 *p = y 692 case *NullDate: 693 if p == nil { 694 return errNilDst(p) 695 } 696 if code != sppb.TypeCode_DATE { 697 return errTypeMismatch(code, acode, ptr) 698 } 699 if isNull { 700 *p = NullDate{} 701 break 702 } 703 x, err := getStringValue(v) 704 if err != nil { 705 return err 706 } 707 y, err := civil.ParseDate(x) 708 if err != nil { 709 return errBadEncoding(v, err) 710 } 711 p.Valid = true 712 p.Date = y 713 case *[]NullDate: 714 if p == nil { 715 return errNilDst(p) 716 } 717 if acode != sppb.TypeCode_DATE { 718 return errTypeMismatch(code, acode, ptr) 719 } 720 if isNull { 721 *p = nil 722 break 723 } 724 x, err := getListValue(v) 725 if err != nil { 726 return err 727 } 728 y, err := decodeNullDateArray(x) 729 if err != nil { 730 return err 731 } 732 *p = y 733 case *[]civil.Date: 734 if p == nil { 735 return errNilDst(p) 736 } 737 if acode != sppb.TypeCode_DATE { 738 return errTypeMismatch(code, acode, ptr) 739 } 740 if isNull { 741 *p = nil 742 break 743 } 744 x, err := getListValue(v) 745 if err != nil { 746 return err 747 } 748 y, err := decodeDateArray(x) 749 if err != nil { 750 return err 751 } 752 *p = y 753 case *[]NullRow: 754 if p == nil { 755 return errNilDst(p) 756 } 757 if acode != sppb.TypeCode_STRUCT { 758 return errTypeMismatch(code, acode, ptr) 759 } 760 if isNull { 761 *p = nil 762 break 763 } 764 x, err := getListValue(v) 765 if err != nil { 766 return err 767 } 768 y, err := decodeRowArray(t.ArrayElementType.StructType, x) 769 if err != nil { 770 return err 771 } 772 *p = y 773 case *GenericColumnValue: 774 *p = GenericColumnValue{Type: t, Value: v} 775 default: 776 // Check if the proto encoding is for an array of structs. 777 if !(code == sppb.TypeCode_ARRAY && acode == sppb.TypeCode_STRUCT) { 778 return errTypeMismatch(code, acode, ptr) 779 } 780 vp := reflect.ValueOf(p) 781 if !vp.IsValid() { 782 return errNilDst(p) 783 } 784 if !isPtrStructPtrSlice(vp.Type()) { 785 // The container is not a pointer to a struct pointer slice. 786 return errTypeMismatch(code, acode, ptr) 787 } 788 // Only use reflection for nil detection on slow path. 789 // Also, IsNil panics on many types, so check it after the type check. 790 if vp.IsNil() { 791 return errNilDst(p) 792 } 793 if isNull { 794 // The proto Value is encoding NULL, set the pointer to struct 795 // slice to nil as well. 796 vp.Elem().Set(reflect.Zero(vp.Elem().Type())) 797 break 798 } 799 x, err := getListValue(v) 800 if err != nil { 801 return err 802 } 803 if err = decodeStructArray(t.ArrayElementType.StructType, x, p); err != nil { 804 return err 805 } 806 } 807 return nil 808} 809 810// errSrvVal returns an error for getting a wrong source protobuf value in decoding. 811func errSrcVal(v *proto3.Value, want string) error { 812 return spannerErrorf(codes.FailedPrecondition, "cannot use %v(Kind: %T) as %s Value", 813 v, v.GetKind(), want) 814} 815 816// getStringValue returns the string value encoded in proto3.Value v whose 817// kind is proto3.Value_StringValue. 818func getStringValue(v *proto3.Value) (string, error) { 819 if x, ok := v.GetKind().(*proto3.Value_StringValue); ok && x != nil { 820 return x.StringValue, nil 821 } 822 return "", errSrcVal(v, "String") 823} 824 825// getBoolValue returns the bool value encoded in proto3.Value v whose 826// kind is proto3.Value_BoolValue. 827func getBoolValue(v *proto3.Value) (bool, error) { 828 if x, ok := v.GetKind().(*proto3.Value_BoolValue); ok && x != nil { 829 return x.BoolValue, nil 830 } 831 return false, errSrcVal(v, "Bool") 832} 833 834// getListValue returns the proto3.ListValue contained in proto3.Value v whose 835// kind is proto3.Value_ListValue. 836func getListValue(v *proto3.Value) (*proto3.ListValue, error) { 837 if x, ok := v.GetKind().(*proto3.Value_ListValue); ok && x != nil { 838 return x.ListValue, nil 839 } 840 return nil, errSrcVal(v, "List") 841} 842 843// errUnexpectedNumStr returns error for decoder getting a unexpected string for 844// representing special float values. 845func errUnexpectedNumStr(s string) error { 846 return spannerErrorf(codes.FailedPrecondition, "unexpected string value %q for number", s) 847} 848 849// getFloat64Value returns the float64 value encoded in proto3.Value v whose 850// kind is proto3.Value_NumberValue / proto3.Value_StringValue. 851// Cloud Spanner uses string to encode NaN, Infinity and -Infinity. 852func getFloat64Value(v *proto3.Value) (float64, error) { 853 switch x := v.GetKind().(type) { 854 case *proto3.Value_NumberValue: 855 if x == nil { 856 break 857 } 858 return x.NumberValue, nil 859 case *proto3.Value_StringValue: 860 if x == nil { 861 break 862 } 863 switch x.StringValue { 864 case "NaN": 865 return math.NaN(), nil 866 case "Infinity": 867 return math.Inf(1), nil 868 case "-Infinity": 869 return math.Inf(-1), nil 870 default: 871 return 0, errUnexpectedNumStr(x.StringValue) 872 } 873 } 874 return 0, errSrcVal(v, "Number") 875} 876 877// errNilListValue returns error for unexpected nil ListValue in decoding Cloud Spanner ARRAYs. 878func errNilListValue(sqlType string) error { 879 return spannerErrorf(codes.FailedPrecondition, "unexpected nil ListValue in decoding %v array", sqlType) 880} 881 882// errDecodeArrayElement returns error for failure in decoding single array element. 883func errDecodeArrayElement(i int, v proto.Message, sqlType string, err error) error { 884 se, ok := toSpannerError(err).(*Error) 885 if !ok { 886 return spannerErrorf(codes.Unknown, 887 "cannot decode %v(array element %v) as %v, error = <%v>", v, i, sqlType, err) 888 } 889 se.decorate(fmt.Sprintf("cannot decode %v(array element %v) as %v", v, i, sqlType)) 890 return se 891} 892 893// decodeNullStringArray decodes proto3.ListValue pb into a NullString slice. 894func decodeNullStringArray(pb *proto3.ListValue) ([]NullString, error) { 895 if pb == nil { 896 return nil, errNilListValue("STRING") 897 } 898 a := make([]NullString, len(pb.Values)) 899 for i, v := range pb.Values { 900 if err := decodeValue(v, stringType(), &a[i]); err != nil { 901 return nil, errDecodeArrayElement(i, v, "STRING", err) 902 } 903 } 904 return a, nil 905} 906 907// decodeStringArray decodes proto3.ListValue pb into a string slice. 908func decodeStringArray(pb *proto3.ListValue) ([]string, error) { 909 if pb == nil { 910 return nil, errNilListValue("STRING") 911 } 912 a := make([]string, len(pb.Values)) 913 st := stringType() 914 for i, v := range pb.Values { 915 if err := decodeValue(v, st, &a[i]); err != nil { 916 return nil, errDecodeArrayElement(i, v, "STRING", err) 917 } 918 } 919 return a, nil 920} 921 922// decodeNullInt64Array decodes proto3.ListValue pb into a NullInt64 slice. 923func decodeNullInt64Array(pb *proto3.ListValue) ([]NullInt64, error) { 924 if pb == nil { 925 return nil, errNilListValue("INT64") 926 } 927 a := make([]NullInt64, len(pb.Values)) 928 for i, v := range pb.Values { 929 if err := decodeValue(v, intType(), &a[i]); err != nil { 930 return nil, errDecodeArrayElement(i, v, "INT64", err) 931 } 932 } 933 return a, nil 934} 935 936// decodeInt64Array decodes proto3.ListValue pb into a int64 slice. 937func decodeInt64Array(pb *proto3.ListValue) ([]int64, error) { 938 if pb == nil { 939 return nil, errNilListValue("INT64") 940 } 941 a := make([]int64, len(pb.Values)) 942 for i, v := range pb.Values { 943 if err := decodeValue(v, intType(), &a[i]); err != nil { 944 return nil, errDecodeArrayElement(i, v, "INT64", err) 945 } 946 } 947 return a, nil 948} 949 950// decodeNullBoolArray decodes proto3.ListValue pb into a NullBool slice. 951func decodeNullBoolArray(pb *proto3.ListValue) ([]NullBool, error) { 952 if pb == nil { 953 return nil, errNilListValue("BOOL") 954 } 955 a := make([]NullBool, len(pb.Values)) 956 for i, v := range pb.Values { 957 if err := decodeValue(v, boolType(), &a[i]); err != nil { 958 return nil, errDecodeArrayElement(i, v, "BOOL", err) 959 } 960 } 961 return a, nil 962} 963 964// decodeBoolArray decodes proto3.ListValue pb into a bool slice. 965func decodeBoolArray(pb *proto3.ListValue) ([]bool, error) { 966 if pb == nil { 967 return nil, errNilListValue("BOOL") 968 } 969 a := make([]bool, len(pb.Values)) 970 for i, v := range pb.Values { 971 if err := decodeValue(v, boolType(), &a[i]); err != nil { 972 return nil, errDecodeArrayElement(i, v, "BOOL", err) 973 } 974 } 975 return a, nil 976} 977 978// decodeNullFloat64Array decodes proto3.ListValue pb into a NullFloat64 slice. 979func decodeNullFloat64Array(pb *proto3.ListValue) ([]NullFloat64, error) { 980 if pb == nil { 981 return nil, errNilListValue("FLOAT64") 982 } 983 a := make([]NullFloat64, len(pb.Values)) 984 for i, v := range pb.Values { 985 if err := decodeValue(v, floatType(), &a[i]); err != nil { 986 return nil, errDecodeArrayElement(i, v, "FLOAT64", err) 987 } 988 } 989 return a, nil 990} 991 992// decodeFloat64Array decodes proto3.ListValue pb into a float64 slice. 993func decodeFloat64Array(pb *proto3.ListValue) ([]float64, error) { 994 if pb == nil { 995 return nil, errNilListValue("FLOAT64") 996 } 997 a := make([]float64, len(pb.Values)) 998 for i, v := range pb.Values { 999 if err := decodeValue(v, floatType(), &a[i]); err != nil { 1000 return nil, errDecodeArrayElement(i, v, "FLOAT64", err) 1001 } 1002 } 1003 return a, nil 1004} 1005 1006// decodeByteArray decodes proto3.ListValue pb into a slice of byte slice. 1007func decodeByteArray(pb *proto3.ListValue) ([][]byte, error) { 1008 if pb == nil { 1009 return nil, errNilListValue("BYTES") 1010 } 1011 a := make([][]byte, len(pb.Values)) 1012 for i, v := range pb.Values { 1013 if err := decodeValue(v, bytesType(), &a[i]); err != nil { 1014 return nil, errDecodeArrayElement(i, v, "BYTES", err) 1015 } 1016 } 1017 return a, nil 1018} 1019 1020// decodeNullTimeArray decodes proto3.ListValue pb into a NullTime slice. 1021func decodeNullTimeArray(pb *proto3.ListValue) ([]NullTime, error) { 1022 if pb == nil { 1023 return nil, errNilListValue("TIMESTAMP") 1024 } 1025 a := make([]NullTime, len(pb.Values)) 1026 for i, v := range pb.Values { 1027 if err := decodeValue(v, timeType(), &a[i]); err != nil { 1028 return nil, errDecodeArrayElement(i, v, "TIMESTAMP", err) 1029 } 1030 } 1031 return a, nil 1032} 1033 1034// decodeTimeArray decodes proto3.ListValue pb into a time.Time slice. 1035func decodeTimeArray(pb *proto3.ListValue) ([]time.Time, error) { 1036 if pb == nil { 1037 return nil, errNilListValue("TIMESTAMP") 1038 } 1039 a := make([]time.Time, len(pb.Values)) 1040 for i, v := range pb.Values { 1041 if err := decodeValue(v, timeType(), &a[i]); err != nil { 1042 return nil, errDecodeArrayElement(i, v, "TIMESTAMP", err) 1043 } 1044 } 1045 return a, nil 1046} 1047 1048// decodeNullDateArray decodes proto3.ListValue pb into a NullDate slice. 1049func decodeNullDateArray(pb *proto3.ListValue) ([]NullDate, error) { 1050 if pb == nil { 1051 return nil, errNilListValue("DATE") 1052 } 1053 a := make([]NullDate, len(pb.Values)) 1054 for i, v := range pb.Values { 1055 if err := decodeValue(v, dateType(), &a[i]); err != nil { 1056 return nil, errDecodeArrayElement(i, v, "DATE", err) 1057 } 1058 } 1059 return a, nil 1060} 1061 1062// decodeDateArray decodes proto3.ListValue pb into a civil.Date slice. 1063func decodeDateArray(pb *proto3.ListValue) ([]civil.Date, error) { 1064 if pb == nil { 1065 return nil, errNilListValue("DATE") 1066 } 1067 a := make([]civil.Date, len(pb.Values)) 1068 for i, v := range pb.Values { 1069 if err := decodeValue(v, dateType(), &a[i]); err != nil { 1070 return nil, errDecodeArrayElement(i, v, "DATE", err) 1071 } 1072 } 1073 return a, nil 1074} 1075 1076func errNotStructElement(i int, v *proto3.Value) error { 1077 return errDecodeArrayElement(i, v, "STRUCT", 1078 spannerErrorf(codes.FailedPrecondition, "%v(type: %T) doesn't encode Cloud Spanner STRUCT", v, v)) 1079} 1080 1081// decodeRowArray decodes proto3.ListValue pb into a NullRow slice according to 1082// the structural information given in sppb.StructType ty. 1083func decodeRowArray(ty *sppb.StructType, pb *proto3.ListValue) ([]NullRow, error) { 1084 if pb == nil { 1085 return nil, errNilListValue("STRUCT") 1086 } 1087 a := make([]NullRow, len(pb.Values)) 1088 for i := range pb.Values { 1089 switch v := pb.Values[i].GetKind().(type) { 1090 case *proto3.Value_ListValue: 1091 a[i] = NullRow{ 1092 Row: Row{ 1093 fields: ty.Fields, 1094 vals: v.ListValue.Values, 1095 }, 1096 Valid: true, 1097 } 1098 // Null elements not currently supported by the server, see 1099 // https://cloud.google.com/spanner/docs/query-syntax#using-structs-with-select 1100 case *proto3.Value_NullValue: 1101 // no-op, a[i] is NullRow{} already 1102 default: 1103 return nil, errNotStructElement(i, pb.Values[i]) 1104 } 1105 } 1106 return a, nil 1107} 1108 1109// errNilSpannerStructType returns error for unexpected nil Cloud Spanner STRUCT schema type in decoding. 1110func errNilSpannerStructType() error { 1111 return spannerErrorf(codes.FailedPrecondition, "unexpected nil StructType in decoding Cloud Spanner STRUCT") 1112} 1113 1114// errUnnamedField returns error for decoding a Cloud Spanner STRUCT with unnamed field into a Go struct. 1115func errUnnamedField(ty *sppb.StructType, i int) error { 1116 return spannerErrorf(codes.InvalidArgument, "unnamed field %v in Cloud Spanner STRUCT %+v", i, ty) 1117} 1118 1119// errNoOrDupGoField returns error for decoding a Cloud Spanner 1120// STRUCT into a Go struct which is either missing a field, or has duplicate fields. 1121func errNoOrDupGoField(s interface{}, f string) error { 1122 return spannerErrorf(codes.InvalidArgument, "Go struct %+v(type %T) has no or duplicate fields for Cloud Spanner STRUCT field %v", s, s, f) 1123} 1124 1125// errDupColNames returns error for duplicated Cloud Spanner STRUCT field names found in decoding a Cloud Spanner STRUCT into a Go struct. 1126func errDupSpannerField(f string, ty *sppb.StructType) error { 1127 return spannerErrorf(codes.InvalidArgument, "duplicated field name %q in Cloud Spanner STRUCT %+v", f, ty) 1128} 1129 1130// errDecodeStructField returns error for failure in decoding a single field of a Cloud Spanner STRUCT. 1131func errDecodeStructField(ty *sppb.StructType, f string, err error) error { 1132 se, ok := toSpannerError(err).(*Error) 1133 if !ok { 1134 return spannerErrorf(codes.Unknown, 1135 "cannot decode field %v of Cloud Spanner STRUCT %+v, error = <%v>", f, ty, err) 1136 } 1137 se.decorate(fmt.Sprintf("cannot decode field %v of Cloud Spanner STRUCT %+v", f, ty)) 1138 return se 1139} 1140 1141// decodeStruct decodes proto3.ListValue pb into struct referenced by pointer ptr, according to 1142// the structural information given in sppb.StructType ty. 1143func decodeStruct(ty *sppb.StructType, pb *proto3.ListValue, ptr interface{}) error { 1144 if reflect.ValueOf(ptr).IsNil() { 1145 return errNilDst(ptr) 1146 } 1147 if ty == nil { 1148 return errNilSpannerStructType() 1149 } 1150 // t holds the structural information of ptr. 1151 t := reflect.TypeOf(ptr).Elem() 1152 // v is the actual value that ptr points to. 1153 v := reflect.ValueOf(ptr).Elem() 1154 1155 fields, err := fieldCache.Fields(t) 1156 if err != nil { 1157 return toSpannerError(err) 1158 } 1159 seen := map[string]bool{} 1160 for i, f := range ty.Fields { 1161 if f.Name == "" { 1162 return errUnnamedField(ty, i) 1163 } 1164 sf := fields.Match(f.Name) 1165 if sf == nil { 1166 return errNoOrDupGoField(ptr, f.Name) 1167 } 1168 if seen[f.Name] { 1169 // We don't allow duplicated field name. 1170 return errDupSpannerField(f.Name, ty) 1171 } 1172 // Try to decode a single field. 1173 if err := decodeValue(pb.Values[i], f.Type, v.FieldByIndex(sf.Index).Addr().Interface()); err != nil { 1174 return errDecodeStructField(ty, f.Name, err) 1175 } 1176 // Mark field f.Name as processed. 1177 seen[f.Name] = true 1178 } 1179 return nil 1180} 1181 1182// isPtrStructPtrSlice returns true if ptr is a pointer to a slice of struct pointers. 1183func isPtrStructPtrSlice(t reflect.Type) bool { 1184 if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Slice { 1185 // t is not a pointer to a slice. 1186 return false 1187 } 1188 if t = t.Elem(); t.Elem().Kind() != reflect.Ptr || t.Elem().Elem().Kind() != reflect.Struct { 1189 // the slice that t points to is not a slice of struct pointers. 1190 return false 1191 } 1192 return true 1193} 1194 1195// decodeStructArray decodes proto3.ListValue pb into struct slice referenced by pointer ptr, according to the 1196// structural information given in a sppb.StructType. 1197func decodeStructArray(ty *sppb.StructType, pb *proto3.ListValue, ptr interface{}) error { 1198 if pb == nil { 1199 return errNilListValue("STRUCT") 1200 } 1201 // Type of the struct pointers stored in the slice that ptr points to. 1202 ts := reflect.TypeOf(ptr).Elem().Elem() 1203 // The slice that ptr points to, might be nil at this point. 1204 v := reflect.ValueOf(ptr).Elem() 1205 // Allocate empty slice. 1206 v.Set(reflect.MakeSlice(v.Type(), 0, len(pb.Values))) 1207 // Decode every struct in pb.Values. 1208 for i, pv := range pb.Values { 1209 // Check if pv is a NULL value. 1210 if _, isNull := pv.Kind.(*proto3.Value_NullValue); isNull { 1211 // Append a nil pointer to the slice. 1212 v.Set(reflect.Append(v, reflect.New(ts).Elem())) 1213 continue 1214 } 1215 // Allocate empty struct. 1216 s := reflect.New(ts.Elem()) 1217 // Get proto3.ListValue l from proto3.Value pv. 1218 l, err := getListValue(pv) 1219 if err != nil { 1220 return errDecodeArrayElement(i, pv, "STRUCT", err) 1221 } 1222 // Decode proto3.ListValue l into struct referenced by s.Interface(). 1223 if err = decodeStruct(ty, l, s.Interface()); err != nil { 1224 return errDecodeArrayElement(i, pv, "STRUCT", err) 1225 } 1226 // Append the decoded struct back into the slice. 1227 v.Set(reflect.Append(v, s)) 1228 } 1229 return nil 1230} 1231 1232// errEncoderUnsupportedType returns error for not being able to encode a value of 1233// certain type. 1234func errEncoderUnsupportedType(v interface{}) error { 1235 return spannerErrorf(codes.InvalidArgument, "client doesn't support type %T", v) 1236} 1237 1238// encodeValue encodes a Go native type into a proto3.Value. 1239func encodeValue(v interface{}) (*proto3.Value, *sppb.Type, error) { 1240 pb := &proto3.Value{ 1241 Kind: &proto3.Value_NullValue{NullValue: proto3.NullValue_NULL_VALUE}, 1242 } 1243 var pt *sppb.Type 1244 var err error 1245 switch v := v.(type) { 1246 case nil: 1247 case string: 1248 pb.Kind = stringKind(v) 1249 pt = stringType() 1250 case NullString: 1251 if v.Valid { 1252 return encodeValue(v.StringVal) 1253 } 1254 pt = stringType() 1255 case []string: 1256 if v != nil { 1257 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1258 if err != nil { 1259 return nil, nil, err 1260 } 1261 } 1262 pt = listType(stringType()) 1263 case []NullString: 1264 if v != nil { 1265 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1266 if err != nil { 1267 return nil, nil, err 1268 } 1269 } 1270 pt = listType(stringType()) 1271 case []byte: 1272 if v != nil { 1273 pb.Kind = stringKind(base64.StdEncoding.EncodeToString(v)) 1274 } 1275 pt = bytesType() 1276 case [][]byte: 1277 if v != nil { 1278 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1279 if err != nil { 1280 return nil, nil, err 1281 } 1282 } 1283 pt = listType(bytesType()) 1284 case int: 1285 pb.Kind = stringKind(strconv.FormatInt(int64(v), 10)) 1286 pt = intType() 1287 case []int: 1288 if v != nil { 1289 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1290 if err != nil { 1291 return nil, nil, err 1292 } 1293 } 1294 pt = listType(intType()) 1295 case int64: 1296 pb.Kind = stringKind(strconv.FormatInt(v, 10)) 1297 pt = intType() 1298 case []int64: 1299 if v != nil { 1300 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1301 if err != nil { 1302 return nil, nil, err 1303 } 1304 } 1305 pt = listType(intType()) 1306 case NullInt64: 1307 if v.Valid { 1308 return encodeValue(v.Int64) 1309 } 1310 pt = intType() 1311 case []NullInt64: 1312 if v != nil { 1313 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1314 if err != nil { 1315 return nil, nil, err 1316 } 1317 } 1318 pt = listType(intType()) 1319 case bool: 1320 pb.Kind = &proto3.Value_BoolValue{BoolValue: v} 1321 pt = boolType() 1322 case []bool: 1323 if v != nil { 1324 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1325 if err != nil { 1326 return nil, nil, err 1327 } 1328 } 1329 pt = listType(boolType()) 1330 case NullBool: 1331 if v.Valid { 1332 return encodeValue(v.Bool) 1333 } 1334 pt = boolType() 1335 case []NullBool: 1336 if v != nil { 1337 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1338 if err != nil { 1339 return nil, nil, err 1340 } 1341 } 1342 pt = listType(boolType()) 1343 case float64: 1344 pb.Kind = &proto3.Value_NumberValue{NumberValue: v} 1345 pt = floatType() 1346 case []float64: 1347 if v != nil { 1348 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1349 if err != nil { 1350 return nil, nil, err 1351 } 1352 } 1353 pt = listType(floatType()) 1354 case NullFloat64: 1355 if v.Valid { 1356 return encodeValue(v.Float64) 1357 } 1358 pt = floatType() 1359 case []NullFloat64: 1360 if v != nil { 1361 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1362 if err != nil { 1363 return nil, nil, err 1364 } 1365 } 1366 pt = listType(floatType()) 1367 case time.Time: 1368 if v == commitTimestamp { 1369 pb.Kind = stringKind(commitTimestampPlaceholderString) 1370 } else { 1371 pb.Kind = stringKind(v.UTC().Format(time.RFC3339Nano)) 1372 } 1373 pt = timeType() 1374 case []time.Time: 1375 if v != nil { 1376 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1377 if err != nil { 1378 return nil, nil, err 1379 } 1380 } 1381 pt = listType(timeType()) 1382 case NullTime: 1383 if v.Valid { 1384 return encodeValue(v.Time) 1385 } 1386 pt = timeType() 1387 case []NullTime: 1388 if v != nil { 1389 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1390 if err != nil { 1391 return nil, nil, err 1392 } 1393 } 1394 pt = listType(timeType()) 1395 case civil.Date: 1396 pb.Kind = stringKind(v.String()) 1397 pt = dateType() 1398 case []civil.Date: 1399 if v != nil { 1400 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1401 if err != nil { 1402 return nil, nil, err 1403 } 1404 } 1405 pt = listType(dateType()) 1406 case NullDate: 1407 if v.Valid { 1408 return encodeValue(v.Date) 1409 } 1410 pt = dateType() 1411 case []NullDate: 1412 if v != nil { 1413 pb, err = encodeArray(len(v), func(i int) interface{} { return v[i] }) 1414 if err != nil { 1415 return nil, nil, err 1416 } 1417 } 1418 pt = listType(dateType()) 1419 case GenericColumnValue: 1420 // Deep clone to ensure subsequent changes to v before 1421 // transmission don't affect our encoded value. 1422 pb = proto.Clone(v.Value).(*proto3.Value) 1423 pt = proto.Clone(v.Type).(*sppb.Type) 1424 case []GenericColumnValue: 1425 return nil, nil, errEncoderUnsupportedType(v) 1426 default: 1427 if !isStructOrArrayOfStructValue(v) { 1428 return nil, nil, errEncoderUnsupportedType(v) 1429 } 1430 typ := reflect.TypeOf(v) 1431 1432 // Value is a Go struct value/ptr. 1433 if (typ.Kind() == reflect.Struct) || 1434 (typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct) { 1435 return encodeStruct(v) 1436 } 1437 1438 // Value is a slice of Go struct values/ptrs. 1439 if typ.Kind() == reflect.Slice { 1440 return encodeStructArray(v) 1441 } 1442 } 1443 return pb, pt, nil 1444} 1445 1446// Encodes a Go struct value/ptr in v to the spanner Value and Type protos. v itself must 1447// be non-nil. 1448func encodeStruct(v interface{}) (*proto3.Value, *sppb.Type, error) { 1449 typ := reflect.TypeOf(v) 1450 val := reflect.ValueOf(v) 1451 1452 // Pointer to struct. 1453 if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct { 1454 typ = typ.Elem() 1455 if val.IsNil() { 1456 // nil pointer to struct, representing a NULL STRUCT value. Use a dummy value to 1457 // get the type. 1458 _, st, err := encodeStruct(reflect.Zero(typ).Interface()) 1459 if err != nil { 1460 return nil, nil, err 1461 } 1462 return nullProto(), st, nil 1463 } 1464 val = val.Elem() 1465 } 1466 1467 if typ.Kind() != reflect.Struct { 1468 return nil, nil, errEncoderUnsupportedType(v) 1469 } 1470 1471 stf := make([]*sppb.StructType_Field, 0, typ.NumField()) 1472 stv := make([]*proto3.Value, 0, typ.NumField()) 1473 1474 for i := 0; i < typ.NumField(); i++ { 1475 // If the field has a 'spanner' tag, use the value of that tag as the field name. 1476 // This is used to build STRUCT types with unnamed/duplicate fields. 1477 sf := typ.Field(i) 1478 fval := val.Field(i) 1479 1480 // Embedded fields are not allowed. 1481 if sf.Anonymous { 1482 return nil, nil, errUnsupportedEmbeddedStructFields(sf.Name) 1483 } 1484 1485 // Unexported fields are ignored. 1486 if !fval.CanInterface() { 1487 continue 1488 } 1489 1490 fname, ok := sf.Tag.Lookup("spanner") 1491 if !ok { 1492 fname = sf.Name 1493 } 1494 1495 eval, etype, err := encodeValue(fval.Interface()) 1496 if err != nil { 1497 return nil, nil, err 1498 } 1499 1500 stf = append(stf, mkField(fname, etype)) 1501 stv = append(stv, eval) 1502 } 1503 1504 return listProto(stv...), structType(stf...), nil 1505} 1506 1507// Encodes a slice of Go struct values/ptrs in v to the spanner Value and Type protos. v itself 1508// must be non-nil. 1509func encodeStructArray(v interface{}) (*proto3.Value, *sppb.Type, error) { 1510 etyp := reflect.TypeOf(v).Elem() 1511 sliceval := reflect.ValueOf(v) 1512 1513 // Slice of pointers to structs. 1514 if etyp.Kind() == reflect.Ptr { 1515 etyp = etyp.Elem() 1516 } 1517 1518 // Use a dummy struct value to get the element type 1519 _, elemTyp, err := encodeStruct(reflect.Zero(etyp).Interface()) 1520 if err != nil { 1521 return nil, nil, err 1522 } 1523 1524 // nil slice represents a NULL array-of-struct. 1525 if sliceval.IsNil() { 1526 return nullProto(), listType(elemTyp), nil 1527 } 1528 1529 values := make([]*proto3.Value, 0, sliceval.Len()) 1530 1531 for i := 0; i < sliceval.Len(); i++ { 1532 ev, _, err := encodeStruct(sliceval.Index(i).Interface()) 1533 if err != nil { 1534 return nil, nil, err 1535 } 1536 values = append(values, ev) 1537 } 1538 return listProto(values...), listType(elemTyp), nil 1539} 1540 1541func isStructOrArrayOfStructValue(v interface{}) bool { 1542 typ := reflect.TypeOf(v) 1543 if typ.Kind() == reflect.Slice { 1544 typ = typ.Elem() 1545 } 1546 if typ.Kind() == reflect.Ptr { 1547 typ = typ.Elem() 1548 } 1549 return typ.Kind() == reflect.Struct 1550} 1551 1552func isSupportedMutationType(v interface{}) bool { 1553 switch v.(type) { 1554 case nil, string, NullString, []string, []NullString, 1555 []byte, [][]byte, 1556 int, []int, int64, []int64, NullInt64, []NullInt64, 1557 bool, []bool, NullBool, []NullBool, 1558 float64, []float64, NullFloat64, []NullFloat64, 1559 time.Time, []time.Time, NullTime, []NullTime, 1560 civil.Date, []civil.Date, NullDate, []NullDate, 1561 GenericColumnValue: 1562 return true 1563 default: 1564 return false 1565 } 1566} 1567 1568// encodeValueArray encodes a Value array into a proto3.ListValue. 1569func encodeValueArray(vs []interface{}) (*proto3.ListValue, error) { 1570 lv := &proto3.ListValue{} 1571 lv.Values = make([]*proto3.Value, 0, len(vs)) 1572 for _, v := range vs { 1573 if !isSupportedMutationType(v) { 1574 return nil, errEncoderUnsupportedType(v) 1575 } 1576 pb, _, err := encodeValue(v) 1577 if err != nil { 1578 return nil, err 1579 } 1580 lv.Values = append(lv.Values, pb) 1581 } 1582 return lv, nil 1583} 1584 1585// encodeArray assumes that all values of the array element type encode without error. 1586func encodeArray(len int, at func(int) interface{}) (*proto3.Value, error) { 1587 vs := make([]*proto3.Value, len) 1588 var err error 1589 for i := 0; i < len; i++ { 1590 vs[i], _, err = encodeValue(at(i)) 1591 if err != nil { 1592 return nil, err 1593 } 1594 } 1595 return listProto(vs...), nil 1596} 1597 1598func spannerTagParser(t reflect.StructTag) (name string, keep bool, other interface{}, err error) { 1599 if s := t.Get("spanner"); s != "" { 1600 if s == "-" { 1601 return "", false, nil, nil 1602 } 1603 return s, true, nil, nil 1604 } 1605 return "", true, nil, nil 1606} 1607 1608var fieldCache = fields.NewCache(spannerTagParser, nil, nil) 1609