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	"reflect"
22	"strconv"
23	"strings"
24	"testing"
25	"time"
26
27	"cloud.google.com/go/civil"
28	"cloud.google.com/go/internal/testutil"
29	proto "github.com/golang/protobuf/proto"
30	proto3 "github.com/golang/protobuf/ptypes/struct"
31	"github.com/google/go-cmp/cmp"
32	sppb "google.golang.org/genproto/googleapis/spanner/v1"
33)
34
35var (
36	tm    = time.Date(2016, 11, 15, 0, 0, 0, 0, time.UTC)
37	dt, _ = civil.ParseDate("2016-11-15")
38	// row contains a column for each unique Cloud Spanner type.
39	row = Row{
40		[]*sppb.StructType_Field{
41			// STRING / STRING ARRAY
42			{Name: "STRING", Type: stringType()},
43			{Name: "NULL_STRING", Type: stringType()},
44			{Name: "STRING_ARRAY", Type: listType(stringType())},
45			{Name: "NULL_STRING_ARRAY", Type: listType(stringType())},
46			// BYTES / BYTES ARRAY
47			{Name: "BYTES", Type: bytesType()},
48			{Name: "NULL_BYTES", Type: bytesType()},
49			{Name: "BYTES_ARRAY", Type: listType(bytesType())},
50			{Name: "NULL_BYTES_ARRAY", Type: listType(bytesType())},
51			// INT64 / INT64 ARRAY
52			{Name: "INT64", Type: intType()},
53			{Name: "NULL_INT64", Type: intType()},
54			{Name: "INT64_ARRAY", Type: listType(intType())},
55			{Name: "NULL_INT64_ARRAY", Type: listType(intType())},
56			// BOOL / BOOL ARRAY
57			{Name: "BOOL", Type: boolType()},
58			{Name: "NULL_BOOL", Type: boolType()},
59			{Name: "BOOL_ARRAY", Type: listType(boolType())},
60			{Name: "NULL_BOOL_ARRAY", Type: listType(boolType())},
61			// FLOAT64 / FLOAT64 ARRAY
62			{Name: "FLOAT64", Type: floatType()},
63			{Name: "NULL_FLOAT64", Type: floatType()},
64			{Name: "FLOAT64_ARRAY", Type: listType(floatType())},
65			{Name: "NULL_FLOAT64_ARRAY", Type: listType(floatType())},
66			// TIMESTAMP / TIMESTAMP ARRAY
67			{Name: "TIMESTAMP", Type: timeType()},
68			{Name: "NULL_TIMESTAMP", Type: timeType()},
69			{Name: "TIMESTAMP_ARRAY", Type: listType(timeType())},
70			{Name: "NULL_TIMESTAMP_ARRAY", Type: listType(timeType())},
71			// DATE / DATE ARRAY
72			{Name: "DATE", Type: dateType()},
73			{Name: "NULL_DATE", Type: dateType()},
74			{Name: "DATE_ARRAY", Type: listType(dateType())},
75			{Name: "NULL_DATE_ARRAY", Type: listType(dateType())},
76
77			// STRUCT ARRAY
78			{
79				Name: "STRUCT_ARRAY",
80				Type: listType(
81					structType(
82						mkField("Col1", intType()),
83						mkField("Col2", floatType()),
84						mkField("Col3", stringType()),
85					),
86				),
87			},
88			{
89				Name: "NULL_STRUCT_ARRAY",
90				Type: listType(
91					structType(
92						mkField("Col1", intType()),
93						mkField("Col2", floatType()),
94						mkField("Col3", stringType()),
95					),
96				),
97			},
98		},
99		[]*proto3.Value{
100			// STRING / STRING ARRAY
101			stringProto("value"),
102			nullProto(),
103			listProto(stringProto("value1"), nullProto(), stringProto("value3")),
104			nullProto(),
105			// BYTES / BYTES ARRAY
106			bytesProto([]byte("value")),
107			nullProto(),
108			listProto(bytesProto([]byte("value1")), nullProto(), bytesProto([]byte("value3"))),
109			nullProto(),
110			// INT64 / INT64 ARRAY
111			intProto(17),
112			nullProto(),
113			listProto(intProto(1), intProto(2), nullProto()),
114			nullProto(),
115			// BOOL / BOOL ARRAY
116			boolProto(true),
117			nullProto(),
118			listProto(nullProto(), boolProto(true), boolProto(false)),
119			nullProto(),
120			// FLOAT64 / FLOAT64 ARRAY
121			floatProto(1.7),
122			nullProto(),
123			listProto(nullProto(), nullProto(), floatProto(1.7)),
124			nullProto(),
125			// TIMESTAMP / TIMESTAMP ARRAY
126			timeProto(tm),
127			nullProto(),
128			listProto(nullProto(), timeProto(tm)),
129			nullProto(),
130			// DATE / DATE ARRAY
131			dateProto(dt),
132			nullProto(),
133			listProto(nullProto(), dateProto(dt)),
134			nullProto(),
135			// STRUCT ARRAY
136			listProto(
137				nullProto(),
138				listProto(intProto(3), floatProto(33.3), stringProto("three")),
139				nullProto(),
140			),
141			nullProto(),
142		},
143	}
144)
145
146// Test helpers for getting column values.
147func TestColumnValues(t *testing.T) {
148	vals := []interface{}{}
149	wantVals := []interface{}{}
150	// Test getting column values.
151	for i, wants := range [][]interface{}{
152		// STRING / STRING ARRAY
153		{"value", NullString{"value", true}},
154		{NullString{}},
155		{[]NullString{{"value1", true}, {}, {"value3", true}}},
156		{[]NullString(nil)},
157		// BYTES / BYTES ARRAY
158		{[]byte("value")},
159		{[]byte(nil)},
160		{[][]byte{[]byte("value1"), nil, []byte("value3")}},
161		{[][]byte(nil)},
162		// INT64 / INT64 ARRAY
163		{int64(17), NullInt64{17, true}},
164		{NullInt64{}},
165		{[]NullInt64{{1, true}, {2, true}, {}}},
166		{[]NullInt64(nil)},
167		// BOOL / BOOL ARRAY
168		{true, NullBool{true, true}},
169		{NullBool{}},
170		{[]NullBool{{}, {true, true}, {false, true}}},
171		{[]NullBool(nil)},
172		// FLOAT64 / FLOAT64 ARRAY
173		{1.7, NullFloat64{1.7, true}},
174		{NullFloat64{}},
175		{[]NullFloat64{{}, {}, {1.7, true}}},
176		{[]NullFloat64(nil)},
177		// TIMESTAMP / TIMESTAMP ARRAY
178		{tm, NullTime{tm, true}},
179		{NullTime{}},
180		{[]NullTime{{}, {tm, true}}},
181		{[]NullTime(nil)},
182		// DATE / DATE ARRAY
183		{dt, NullDate{dt, true}},
184		{NullDate{}},
185		{[]NullDate{{}, {dt, true}}},
186		{[]NullDate(nil)},
187		// STRUCT ARRAY
188		{
189			[]*struct {
190				Col1 NullInt64
191				Col2 NullFloat64
192				Col3 string
193			}{
194				nil,
195
196				{
197					NullInt64{3, true},
198					NullFloat64{33.3, true},
199					"three",
200				},
201				nil,
202			},
203			[]NullRow{
204				{},
205				{
206					Row: Row{
207						fields: []*sppb.StructType_Field{
208							mkField("Col1", intType()),
209							mkField("Col2", floatType()),
210							mkField("Col3", stringType()),
211						},
212						vals: []*proto3.Value{
213							intProto(3),
214							floatProto(33.3),
215							stringProto("three"),
216						},
217					},
218					Valid: true,
219				},
220				{},
221			},
222		},
223		{
224			[]*struct {
225				Col1 NullInt64
226				Col2 NullFloat64
227				Col3 string
228			}(nil),
229			[]NullRow(nil),
230		},
231	} {
232		for j, want := range wants {
233			// Prepare Value vector to test Row.Columns.
234			if j == 0 {
235				vals = append(vals, reflect.New(reflect.TypeOf(want)).Interface())
236				wantVals = append(wantVals, want)
237			}
238			// Column
239			gotp := reflect.New(reflect.TypeOf(want))
240			err := row.Column(i, gotp.Interface())
241			if err != nil {
242				t.Errorf("\t row.Column(%v, %T) returns error: %v, want nil", i, gotp.Interface(), err)
243			}
244			if got := reflect.Indirect(gotp).Interface(); !testEqual(got, want) {
245				t.Errorf("\t row.Column(%v, %T) retrives %v, want %v", i, gotp.Interface(), got, want)
246			}
247			// ColumnByName
248			gotp = reflect.New(reflect.TypeOf(want))
249			err = row.ColumnByName(row.fields[i].Name, gotp.Interface())
250			if err != nil {
251				t.Errorf("\t row.ColumnByName(%v, %T) returns error: %v, want nil", row.fields[i].Name, gotp.Interface(), err)
252			}
253			if got := reflect.Indirect(gotp).Interface(); !testEqual(got, want) {
254				t.Errorf("\t row.ColumnByName(%v, %T) retrives %v, want %v", row.fields[i].Name, gotp.Interface(), got, want)
255			}
256		}
257	}
258	// Test Row.Columns.
259	if err := row.Columns(vals...); err != nil {
260		t.Errorf("row.Columns() returns error: %v, want nil", err)
261	}
262	for i, want := range wantVals {
263		if got := reflect.Indirect(reflect.ValueOf(vals[i])).Interface(); !testEqual(got, want) {
264			t.Errorf("\t got %v(%T) for column[%v], want %v(%T)", got, got, row.fields[i].Name, want, want)
265		}
266	}
267}
268
269// Test decoding into nil destination.
270func TestNilDst(t *testing.T) {
271	for i, test := range []struct {
272		r               *Row
273		dst             interface{}
274		wantErr         error
275		structDst       interface{}
276		wantToStructErr error
277	}{
278		{
279			&Row{
280				[]*sppb.StructType_Field{
281					{Name: "Col0", Type: stringType()},
282				},
283				[]*proto3.Value{stringProto("value")},
284			},
285			nil,
286			errDecodeColumn(0, errNilDst(nil)),
287			nil,
288			errToStructArgType(nil),
289		},
290		{
291			&Row{
292				[]*sppb.StructType_Field{
293					{Name: "Col0", Type: stringType()},
294				},
295				[]*proto3.Value{stringProto("value")},
296			},
297			(*string)(nil),
298			errDecodeColumn(0, errNilDst((*string)(nil))),
299			(*struct{ STRING string })(nil),
300			errNilDst((*struct{ STRING string })(nil)),
301		},
302		{
303			&Row{
304				[]*sppb.StructType_Field{
305					{
306						Name: "Col0",
307						Type: listType(
308							structType(
309								mkField("Col1", intType()),
310								mkField("Col2", floatType()),
311							),
312						),
313					},
314				},
315				[]*proto3.Value{listProto(
316					listProto(intProto(3), floatProto(33.3)),
317				)},
318			},
319			(*[]*struct {
320				Col1 int
321				Col2 float64
322			})(nil),
323			errDecodeColumn(0, errNilDst((*[]*struct {
324				Col1 int
325				Col2 float64
326			})(nil))),
327			(*struct {
328				StructArray []*struct {
329					Col1 int
330					Col2 float64
331				} `spanner:"STRUCT_ARRAY"`
332			})(nil),
333			errNilDst((*struct {
334				StructArray []*struct {
335					Col1 int
336					Col2 float64
337				} `spanner:"STRUCT_ARRAY"`
338			})(nil)),
339		},
340	} {
341		if gotErr := test.r.Column(0, test.dst); !testEqual(gotErr, test.wantErr) {
342			t.Errorf("%v: test.r.Column() returns error %v, want %v", i, gotErr, test.wantErr)
343		}
344		if gotErr := test.r.ColumnByName("Col0", test.dst); !testEqual(gotErr, test.wantErr) {
345			t.Errorf("%v: test.r.ColumnByName() returns error %v, want %v", i, gotErr, test.wantErr)
346		}
347		// Row.Columns(T) should return nil on T == nil, otherwise, it should return test.wantErr.
348		wantColumnsErr := test.wantErr
349		if test.dst == nil {
350			wantColumnsErr = nil
351		}
352		if gotErr := test.r.Columns(test.dst); !testEqual(gotErr, wantColumnsErr) {
353			t.Errorf("%v: test.r.Columns() returns error %v, want %v", i, gotErr, wantColumnsErr)
354		}
355		if gotErr := test.r.ToStruct(test.structDst); !testEqual(gotErr, test.wantToStructErr) {
356			t.Errorf("%v: test.r.ToStruct() returns error %v, want %v", i, gotErr, test.wantToStructErr)
357		}
358	}
359}
360
361// Test decoding NULL columns using Go types that don't support NULL.
362func TestNullTypeErr(t *testing.T) {
363	var tm time.Time
364	ntoi := func(n string) int {
365		for i, f := range row.fields {
366			if f.Name == n {
367				return i
368			}
369		}
370		t.Errorf("cannot find column name %q in row", n)
371		return 0
372	}
373	for _, test := range []struct {
374		colName string
375		dst     interface{}
376	}{
377		{
378			"NULL_STRING",
379			proto.String(""),
380		},
381		{
382			"NULL_INT64",
383			proto.Int64(0),
384		},
385		{
386			"NULL_BOOL",
387			proto.Bool(false),
388		},
389		{
390			"NULL_FLOAT64",
391			proto.Float64(0.0),
392		},
393		{
394			"NULL_TIMESTAMP",
395			&tm,
396		},
397		{
398			"NULL_DATE",
399			&dt,
400		},
401	} {
402		wantErr := errDecodeColumn(ntoi(test.colName), errDstNotForNull(test.dst))
403		if gotErr := row.ColumnByName(test.colName, test.dst); !testEqual(gotErr, wantErr) {
404			t.Errorf("row.ColumnByName(%v) returns error %v, want %v", test.colName, gotErr, wantErr)
405		}
406	}
407}
408
409// Test using wrong destination type in column decoders.
410func TestColumnTypeErr(t *testing.T) {
411	// badDst cannot hold any of the column values.
412	badDst := &struct{}{}
413	for i, f := range row.fields { // For each of the columns, try to decode it into badDst.
414		tc := f.Type.Code
415		var etc sppb.TypeCode
416		if strings.Contains(f.Name, "ARRAY") {
417			etc = f.Type.ArrayElementType.Code
418		}
419		wantErr := errDecodeColumn(i, errTypeMismatch(tc, etc, badDst))
420		if gotErr := row.Column(i, badDst); !testEqual(gotErr, wantErr) {
421			t.Errorf("Column(%v): decoding into destination with wrong type %T returns error %v, want %v",
422				i, badDst, gotErr, wantErr)
423		}
424		if gotErr := row.ColumnByName(f.Name, badDst); !testEqual(gotErr, wantErr) {
425			t.Errorf("ColumnByName(%v): decoding into destination with wrong type %T returns error %v, want %v",
426				f.Name, badDst, gotErr, wantErr)
427		}
428	}
429	wantErr := errDecodeColumn(1, errTypeMismatch(sppb.TypeCode_STRING, sppb.TypeCode_TYPE_CODE_UNSPECIFIED, badDst))
430	// badDst is used to receive column 1.
431	vals := []interface{}{nil, badDst} // Row.Column() is expected to fail at column 1.
432	// Skip decoding the rest columns by providing nils as the destinations.
433	for i := 2; i < len(row.fields); i++ {
434		vals = append(vals, nil)
435	}
436	if gotErr := row.Columns(vals...); !testEqual(gotErr, wantErr) {
437		t.Errorf("Columns(): decoding column 1 with wrong type %T returns error %v, want %v",
438			badDst, gotErr, wantErr)
439	}
440}
441
442// Test the handling of invalid column decoding requests which cannot be mapped to correct column(s).
443func TestInvalidColumnRequest(t *testing.T) {
444	for _, test := range []struct {
445		desc    string
446		f       func() error
447		wantErr error
448	}{
449		{
450			"Request column index is out of range",
451			func() error {
452				return row.Column(10000, &struct{}{})
453			},
454			errColIdxOutOfRange(10000, &row),
455		},
456		{
457			"Cannot find the named column",
458			func() error {
459				return row.ColumnByName("string", &struct{}{})
460			},
461			errColNotFound("string"),
462		},
463		{
464			"Not enough arguments to call row.Columns()",
465			func() error {
466				return row.Columns(nil, nil)
467			},
468			errNumOfColValue(2, &row),
469		},
470		{
471			"Call ColumnByName on row with duplicated column names",
472			func() error {
473				var s string
474				r := &Row{
475					[]*sppb.StructType_Field{
476						{Name: "Val", Type: stringType()},
477						{Name: "Val", Type: stringType()},
478					},
479					[]*proto3.Value{stringProto("value1"), stringProto("value2")},
480				}
481				return r.ColumnByName("Val", &s)
482			},
483			errDupColName("Val"),
484		},
485		{
486			"Call ToStruct on row with duplicated column names",
487			func() error {
488				s := &struct {
489					Val string
490				}{}
491				r := &Row{
492					[]*sppb.StructType_Field{
493						{Name: "Val", Type: stringType()},
494						{Name: "Val", Type: stringType()},
495					},
496					[]*proto3.Value{stringProto("value1"), stringProto("value2")},
497				}
498				return r.ToStruct(s)
499			},
500			errDupSpannerField("Val", &sppb.StructType{
501				Fields: []*sppb.StructType_Field{
502					{Name: "Val", Type: stringType()},
503					{Name: "Val", Type: stringType()},
504				},
505			}),
506		},
507		{
508			"Call ToStruct on a row with unnamed field",
509			func() error {
510				s := &struct {
511					Val string
512				}{}
513				r := &Row{
514					[]*sppb.StructType_Field{
515						{Name: "", Type: stringType()},
516					},
517					[]*proto3.Value{stringProto("value1")},
518				}
519				return r.ToStruct(s)
520			},
521			errUnnamedField(&sppb.StructType{Fields: []*sppb.StructType_Field{
522				{Name: "", Type: stringType()},
523			}}, 0),
524		},
525	} {
526		if gotErr := test.f(); !testEqual(gotErr, test.wantErr) {
527			t.Errorf("%v: test.f() returns error %v, want %v", test.desc, gotErr, test.wantErr)
528		}
529	}
530}
531
532// Test decoding the row with row.ToStruct into an invalid destination.
533func TestToStructInvalidDst(t *testing.T) {
534	for _, test := range []struct {
535		desc    string
536		dst     interface{}
537		wantErr error
538	}{
539		{
540			"Decode row as STRUCT into int32",
541			proto.Int(1),
542			errToStructArgType(proto.Int(1)),
543		},
544		{
545			"Decode row as STRUCT to nil Go struct",
546			(*struct{})(nil),
547			errNilDst((*struct{})(nil)),
548		},
549		{
550			"Decode row as STRUCT to Go struct with duplicated fields for the PK column",
551			&struct {
552				PK1 string `spanner:"STRING"`
553				PK2 string `spanner:"STRING"`
554			}{},
555			errNoOrDupGoField(&struct {
556				PK1 string `spanner:"STRING"`
557				PK2 string `spanner:"STRING"`
558			}{}, "STRING"),
559		},
560		{
561			"Decode row as STRUCT to Go struct with no field for the PK column",
562			&struct {
563				PK1 string `spanner:"_STRING"`
564			}{},
565			errNoOrDupGoField(&struct {
566				PK1 string `spanner:"_STRING"`
567			}{}, "STRING"),
568		},
569		{
570			"Decode row as STRUCT to Go struct with wrong type for the PK column",
571			&struct {
572				PK1 int64 `spanner:"STRING"`
573			}{},
574			errDecodeStructField(&sppb.StructType{Fields: row.fields}, "STRING",
575				errTypeMismatch(sppb.TypeCode_STRING, sppb.TypeCode_TYPE_CODE_UNSPECIFIED, proto.Int64(0))),
576		},
577	} {
578		if gotErr := row.ToStruct(test.dst); !testEqual(gotErr, test.wantErr) {
579			t.Errorf("%v: decoding:\ngot  %v\nwant %v", test.desc, gotErr, test.wantErr)
580		}
581	}
582}
583
584// Test decoding a broken row.
585func TestBrokenRow(t *testing.T) {
586	for i, test := range []struct {
587		row     *Row
588		dst     interface{}
589		wantErr error
590	}{
591		{
592			// A row with no field.
593			&Row{
594				[]*sppb.StructType_Field{},
595				[]*proto3.Value{stringProto("value")},
596			},
597			&NullString{"value", true},
598			errFieldsMismatchVals(&Row{
599				[]*sppb.StructType_Field{},
600				[]*proto3.Value{stringProto("value")},
601			}),
602		},
603		{
604			// A row with nil field.
605			&Row{
606				[]*sppb.StructType_Field{nil},
607				[]*proto3.Value{stringProto("value")},
608			},
609			&NullString{"value", true},
610			errNilColType(0),
611		},
612		{
613			// Field is not nil, but its type is nil.
614			&Row{
615				[]*sppb.StructType_Field{
616					{Name: "Col0", Type: nil},
617				},
618				[]*proto3.Value{listProto(stringProto("value1"), stringProto("value2"))},
619			},
620			&[]NullString{},
621			errDecodeColumn(0, errNilSpannerType()),
622		},
623		{
624			// Field is not nil, field type is not nil, but it is an array and its array element type is nil.
625			&Row{
626				[]*sppb.StructType_Field{
627					{Name: "Col0", Type: &sppb.Type{Code: sppb.TypeCode_ARRAY}},
628				},
629				[]*proto3.Value{listProto(stringProto("value1"), stringProto("value2"))},
630			},
631			&[]NullString{},
632			errDecodeColumn(0, errNilArrElemType(&sppb.Type{Code: sppb.TypeCode_ARRAY})),
633		},
634		{
635			// Field specifies valid type, value is nil.
636			&Row{
637				[]*sppb.StructType_Field{
638					{Name: "Col0", Type: intType()},
639				},
640				[]*proto3.Value{nil},
641			},
642			&NullInt64{1, true},
643			errDecodeColumn(0, errNilSrc()),
644		},
645		{
646			// Field specifies INT64 type, value is having a nil Kind.
647			&Row{
648				[]*sppb.StructType_Field{
649					{Name: "Col0", Type: intType()},
650				},
651				[]*proto3.Value{{Kind: (*proto3.Value_StringValue)(nil)}},
652			},
653			&NullInt64{1, true},
654			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_StringValue)(nil)}, "String")),
655		},
656		{
657			// Field specifies INT64 type, but value is for Number type.
658			&Row{
659				[]*sppb.StructType_Field{
660					{Name: "Col0", Type: intType()},
661				},
662				[]*proto3.Value{floatProto(1.0)},
663			},
664			&NullInt64{1, true},
665			errDecodeColumn(0, errSrcVal(floatProto(1.0), "String")),
666		},
667		{
668			// Field specifies INT64 type, but value is wrongly encoded.
669			&Row{
670				[]*sppb.StructType_Field{
671					{Name: "Col0", Type: intType()},
672				},
673				[]*proto3.Value{stringProto("&1")},
674			},
675			proto.Int64(0),
676			errDecodeColumn(0, errBadEncoding(stringProto("&1"), func() error {
677				_, err := strconv.ParseInt("&1", 10, 64)
678				return err
679			}())),
680		},
681		{
682			// Field specifies INT64 type, but value is wrongly encoded.
683			&Row{
684				[]*sppb.StructType_Field{
685					{Name: "Col0", Type: intType()},
686				},
687				[]*proto3.Value{stringProto("&1")},
688			},
689			&NullInt64{},
690			errDecodeColumn(0, errBadEncoding(stringProto("&1"), func() error {
691				_, err := strconv.ParseInt("&1", 10, 64)
692				return err
693			}())),
694		},
695		{
696			// Field specifies STRING type, but value is having a nil Kind.
697			&Row{
698				[]*sppb.StructType_Field{
699					{Name: "Col0", Type: stringType()},
700				},
701				[]*proto3.Value{{Kind: (*proto3.Value_StringValue)(nil)}},
702			},
703			&NullString{"value", true},
704			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_StringValue)(nil)}, "String")),
705		},
706		{
707			// Field specifies STRING type, but value is for ARRAY type.
708			&Row{
709				[]*sppb.StructType_Field{
710					{Name: "Col0", Type: stringType()},
711				},
712				[]*proto3.Value{listProto(stringProto("value"))},
713			},
714			&NullString{"value", true},
715			errDecodeColumn(0, errSrcVal(listProto(stringProto("value")), "String")),
716		},
717		{
718			// Field specifies FLOAT64 type, value is having a nil Kind.
719			&Row{
720				[]*sppb.StructType_Field{
721					{Name: "Col0", Type: floatType()},
722				},
723				[]*proto3.Value{{Kind: (*proto3.Value_NumberValue)(nil)}},
724			},
725			&NullFloat64{1.0, true},
726			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_NumberValue)(nil)}, "Number")),
727		},
728		{
729			// Field specifies FLOAT64 type, but value is for BOOL type.
730			&Row{
731				[]*sppb.StructType_Field{
732					{Name: "Col0", Type: floatType()},
733				},
734				[]*proto3.Value{boolProto(true)},
735			},
736			&NullFloat64{1.0, true},
737			errDecodeColumn(0, errSrcVal(boolProto(true), "Number")),
738		},
739		{
740			// Field specifies FLOAT64 type, but value is wrongly encoded.
741			&Row{
742				[]*sppb.StructType_Field{
743					{Name: "Col0", Type: floatType()},
744				},
745				[]*proto3.Value{stringProto("nan")},
746			},
747			&NullFloat64{},
748			errDecodeColumn(0, errUnexpectedNumStr("nan")),
749		},
750		{
751			// Field specifies FLOAT64 type, but value is wrongly encoded.
752			&Row{
753				[]*sppb.StructType_Field{
754					{Name: "Col0", Type: floatType()},
755				},
756				[]*proto3.Value{stringProto("nan")},
757			},
758			proto.Float64(0),
759			errDecodeColumn(0, errUnexpectedNumStr("nan")),
760		},
761		{
762			// Field specifies BYTES type, value is having a nil Kind.
763			&Row{
764				[]*sppb.StructType_Field{
765					{Name: "Col0", Type: bytesType()},
766				},
767				[]*proto3.Value{{Kind: (*proto3.Value_StringValue)(nil)}},
768			},
769			&[]byte{},
770			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_StringValue)(nil)}, "String")),
771		},
772		{
773			// Field specifies BYTES type, but value is for BOOL type.
774			&Row{
775				[]*sppb.StructType_Field{
776					{Name: "Col0", Type: bytesType()},
777				},
778				[]*proto3.Value{boolProto(false)},
779			},
780			&[]byte{},
781			errDecodeColumn(0, errSrcVal(boolProto(false), "String")),
782		},
783		{
784			// Field specifies BYTES type, but value is wrongly encoded.
785			&Row{
786				[]*sppb.StructType_Field{
787					{Name: "Col0", Type: bytesType()},
788				},
789				[]*proto3.Value{stringProto("&&")},
790			},
791			&[]byte{},
792			errDecodeColumn(0, errBadEncoding(stringProto("&&"), func() error {
793				_, err := base64.StdEncoding.DecodeString("&&")
794				return err
795			}())),
796		},
797		{
798			// Field specifies BOOL type, value is having a nil Kind.
799			&Row{
800				[]*sppb.StructType_Field{
801					{Name: "Col0", Type: boolType()},
802				},
803				[]*proto3.Value{{Kind: (*proto3.Value_BoolValue)(nil)}},
804			},
805			&NullBool{false, true},
806			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_BoolValue)(nil)}, "Bool")),
807		},
808		{
809			// Field specifies BOOL type, but value is for STRING type.
810			&Row{
811				[]*sppb.StructType_Field{
812					{Name: "Col0", Type: boolType()},
813				},
814				[]*proto3.Value{stringProto("false")},
815			},
816			&NullBool{false, true},
817			errDecodeColumn(0, errSrcVal(stringProto("false"), "Bool")),
818		},
819		{
820			// Field specifies TIMESTAMP type, value is having a nil Kind.
821			&Row{
822				[]*sppb.StructType_Field{
823					{Name: "Col0", Type: timeType()},
824				},
825				[]*proto3.Value{{Kind: (*proto3.Value_StringValue)(nil)}},
826			},
827			&NullTime{time.Now(), true},
828			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_StringValue)(nil)}, "String")),
829		},
830		{
831			// Field specifies TIMESTAMP type, but value is for BOOL type.
832			&Row{
833				[]*sppb.StructType_Field{
834					{Name: "Col0", Type: timeType()},
835				},
836				[]*proto3.Value{boolProto(false)},
837			},
838			&NullTime{time.Now(), true},
839			errDecodeColumn(0, errSrcVal(boolProto(false), "String")),
840		},
841		{
842			// Field specifies TIMESTAMP type, but value is invalid timestamp.
843			&Row{
844				[]*sppb.StructType_Field{
845					{Name: "Col0", Type: timeType()},
846				},
847				[]*proto3.Value{stringProto("junk")},
848			},
849			&NullTime{time.Now(), true},
850			errDecodeColumn(0, errBadEncoding(stringProto("junk"), func() error {
851				_, err := time.Parse(time.RFC3339Nano, "junk")
852				return err
853			}())),
854		},
855		{
856			// Field specifies DATE type, value is having a nil Kind.
857			&Row{
858				[]*sppb.StructType_Field{
859					{Name: "Col0", Type: dateType()},
860				},
861				[]*proto3.Value{{Kind: (*proto3.Value_StringValue)(nil)}},
862			},
863			&NullDate{civil.Date{}, true},
864			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_StringValue)(nil)}, "String")),
865		},
866		{
867			// Field specifies DATE type, but value is for BOOL type.
868			&Row{
869				[]*sppb.StructType_Field{
870					{Name: "Col0", Type: dateType()},
871				},
872				[]*proto3.Value{boolProto(false)},
873			},
874			&NullDate{civil.Date{}, true},
875			errDecodeColumn(0, errSrcVal(boolProto(false), "String")),
876		},
877		{
878			// Field specifies DATE type, but value is invalid timestamp.
879			&Row{
880				[]*sppb.StructType_Field{
881					{Name: "Col0", Type: dateType()},
882				},
883				[]*proto3.Value{stringProto("junk")},
884			},
885			&NullDate{civil.Date{}, true},
886			errDecodeColumn(0, errBadEncoding(stringProto("junk"), func() error {
887				_, err := civil.ParseDate("junk")
888				return err
889			}())),
890		},
891
892		{
893			// Field specifies ARRAY<INT64> type, value is having a nil Kind.
894			&Row{
895				[]*sppb.StructType_Field{
896					{Name: "Col0", Type: listType(intType())},
897				},
898				[]*proto3.Value{{Kind: (*proto3.Value_ListValue)(nil)}},
899			},
900			&[]NullInt64{},
901			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_ListValue)(nil)}, "List")),
902		},
903		{
904			// Field specifies ARRAY<INT64> type, value is having a nil ListValue.
905			&Row{
906				[]*sppb.StructType_Field{
907					{Name: "Col0", Type: listType(intType())},
908				},
909				[]*proto3.Value{{Kind: &proto3.Value_ListValue{}}},
910			},
911			&[]NullInt64{},
912			errDecodeColumn(0, errNilListValue("INT64")),
913		},
914		{
915			// Field specifies ARRAY<INT64> type, but value is for BYTES type.
916			&Row{
917				[]*sppb.StructType_Field{
918					{Name: "Col0", Type: listType(intType())},
919				},
920				[]*proto3.Value{bytesProto([]byte("value"))},
921			},
922			&[]NullInt64{},
923			errDecodeColumn(0, errSrcVal(bytesProto([]byte("value")), "List")),
924		},
925		{
926			// Field specifies ARRAY<INT64> type, but value is for ARRAY<BOOL> type.
927			&Row{
928				[]*sppb.StructType_Field{
929					{Name: "Col0", Type: listType(intType())},
930				},
931				[]*proto3.Value{listProto(boolProto(true))},
932			},
933			&[]NullInt64{},
934			errDecodeColumn(0, errDecodeArrayElement(0, boolProto(true),
935				"INT64", errSrcVal(boolProto(true), "String"))),
936		},
937		{
938			// Field specifies ARRAY<STRING> type, value is having a nil Kind.
939			&Row{
940				[]*sppb.StructType_Field{
941					{Name: "Col0", Type: listType(stringType())},
942				},
943				[]*proto3.Value{{Kind: (*proto3.Value_ListValue)(nil)}},
944			},
945			&[]NullString{},
946			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_ListValue)(nil)}, "List")),
947		},
948		{
949			// Field specifies ARRAY<STRING> type, value is having a nil ListValue.
950			&Row{
951				[]*sppb.StructType_Field{
952					{Name: "Col0", Type: listType(stringType())},
953				},
954				[]*proto3.Value{{Kind: &proto3.Value_ListValue{}}},
955			},
956			&[]NullString{},
957			errDecodeColumn(0, errNilListValue("STRING")),
958		},
959		{
960			// Field specifies ARRAY<STRING> type, but value is for BOOL type.
961			&Row{
962				[]*sppb.StructType_Field{
963					{Name: "Col0", Type: listType(stringType())},
964				},
965				[]*proto3.Value{boolProto(true)},
966			},
967			&[]NullString{},
968			errDecodeColumn(0, errSrcVal(boolProto(true), "List")),
969		},
970		{
971			// Field specifies ARRAY<STRING> type, but value is for ARRAY<BOOL> type.
972			&Row{
973				[]*sppb.StructType_Field{
974					{Name: "Col0", Type: listType(stringType())},
975				},
976				[]*proto3.Value{listProto(boolProto(true))},
977			},
978			&[]NullString{},
979			errDecodeColumn(0, errDecodeArrayElement(0, boolProto(true),
980				"STRING", errSrcVal(boolProto(true), "String"))),
981		},
982		{
983			// Field specifies ARRAY<FLOAT64> type, value is having a nil Kind.
984			&Row{
985				[]*sppb.StructType_Field{
986					{Name: "Col0", Type: listType(floatType())},
987				},
988				[]*proto3.Value{{Kind: (*proto3.Value_ListValue)(nil)}},
989			},
990			&[]NullFloat64{},
991			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_ListValue)(nil)}, "List")),
992		},
993		{
994			// Field specifies ARRAY<FLOAT64> type, value is having a nil ListValue.
995			&Row{
996				[]*sppb.StructType_Field{
997					{Name: "Col0", Type: listType(floatType())},
998				},
999				[]*proto3.Value{{Kind: &proto3.Value_ListValue{}}},
1000			},
1001			&[]NullFloat64{},
1002			errDecodeColumn(0, errNilListValue("FLOAT64")),
1003		},
1004		{
1005			// Field specifies ARRAY<FLOAT64> type, but value is for STRING type.
1006			&Row{
1007				[]*sppb.StructType_Field{
1008					{Name: "Col0", Type: listType(floatType())},
1009				},
1010				[]*proto3.Value{stringProto("value")},
1011			},
1012			&[]NullFloat64{},
1013			errDecodeColumn(0, errSrcVal(stringProto("value"), "List")),
1014		},
1015		{
1016			// Field specifies ARRAY<FLOAT64> type, but value is for ARRAY<BOOL> type.
1017			&Row{
1018				[]*sppb.StructType_Field{
1019					{Name: "Col0", Type: listType(floatType())},
1020				},
1021				[]*proto3.Value{listProto(boolProto(true))},
1022			},
1023			&[]NullFloat64{},
1024			errDecodeColumn(0, errDecodeArrayElement(0, boolProto(true),
1025				"FLOAT64", errSrcVal(boolProto(true), "Number"))),
1026		},
1027		{
1028			// Field specifies ARRAY<BYTES> type, value is having a nil Kind.
1029			&Row{
1030				[]*sppb.StructType_Field{
1031					{Name: "Col0", Type: listType(bytesType())},
1032				},
1033				[]*proto3.Value{{Kind: (*proto3.Value_ListValue)(nil)}},
1034			},
1035			&[][]byte{},
1036			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_ListValue)(nil)}, "List")),
1037		},
1038		{
1039			// Field specifies ARRAY<BYTES> type, value is having a nil ListValue.
1040			&Row{
1041				[]*sppb.StructType_Field{
1042					{Name: "Col0", Type: listType(bytesType())},
1043				},
1044				[]*proto3.Value{{Kind: &proto3.Value_ListValue{}}},
1045			},
1046			&[][]byte{},
1047			errDecodeColumn(0, errNilListValue("BYTES")),
1048		},
1049		{
1050			// Field specifies ARRAY<BYTES> type, but value is for FLOAT64 type.
1051			&Row{
1052				[]*sppb.StructType_Field{
1053					{Name: "Col0", Type: listType(bytesType())},
1054				},
1055				[]*proto3.Value{floatProto(1.0)},
1056			},
1057			&[][]byte{},
1058			errDecodeColumn(0, errSrcVal(floatProto(1.0), "List")),
1059		},
1060		{
1061			// Field specifies ARRAY<BYTES> type, but value is for ARRAY<FLOAT64> type.
1062			&Row{
1063				[]*sppb.StructType_Field{
1064					{Name: "Col0", Type: listType(bytesType())},
1065				},
1066				[]*proto3.Value{listProto(floatProto(1.0))},
1067			},
1068			&[][]byte{},
1069			errDecodeColumn(0, errDecodeArrayElement(0, floatProto(1.0),
1070				"BYTES", errSrcVal(floatProto(1.0), "String"))),
1071		},
1072		{
1073			// Field specifies ARRAY<BOOL> type, value is having a nil Kind.
1074			&Row{
1075				[]*sppb.StructType_Field{
1076					{Name: "Col0", Type: listType(boolType())},
1077				},
1078				[]*proto3.Value{{Kind: (*proto3.Value_ListValue)(nil)}},
1079			},
1080			&[]NullBool{},
1081			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_ListValue)(nil)}, "List")),
1082		},
1083		{
1084			// Field specifies ARRAY<BOOL> type, value is having a nil ListValue.
1085			&Row{
1086				[]*sppb.StructType_Field{
1087					{Name: "Col0", Type: listType(boolType())},
1088				},
1089				[]*proto3.Value{{Kind: &proto3.Value_ListValue{}}},
1090			},
1091			&[]NullBool{},
1092			errDecodeColumn(0, errNilListValue("BOOL")),
1093		},
1094		{
1095			// Field specifies ARRAY<BOOL> type, but value is for FLOAT64 type.
1096			&Row{
1097				[]*sppb.StructType_Field{
1098					{Name: "Col0", Type: listType(boolType())},
1099				},
1100				[]*proto3.Value{floatProto(1.0)},
1101			},
1102			&[]NullBool{},
1103			errDecodeColumn(0, errSrcVal(floatProto(1.0), "List")),
1104		},
1105		{
1106			// Field specifies ARRAY<BOOL> type, but value is for ARRAY<FLOAT64> type.
1107			&Row{
1108				[]*sppb.StructType_Field{
1109					{Name: "Col0", Type: listType(boolType())},
1110				},
1111				[]*proto3.Value{listProto(floatProto(1.0))},
1112			},
1113			&[]NullBool{},
1114			errDecodeColumn(0, errDecodeArrayElement(0, floatProto(1.0),
1115				"BOOL", errSrcVal(floatProto(1.0), "Bool"))),
1116		},
1117		{
1118			// Field specifies ARRAY<TIMESTAMP> type, value is having a nil Kind.
1119			&Row{
1120				[]*sppb.StructType_Field{
1121					{Name: "Col0", Type: listType(timeType())},
1122				},
1123				[]*proto3.Value{{Kind: (*proto3.Value_ListValue)(nil)}},
1124			},
1125			&[]NullTime{},
1126			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_ListValue)(nil)}, "List")),
1127		},
1128		{
1129			// Field specifies ARRAY<TIMESTAMP> type, value is having a nil ListValue.
1130			&Row{
1131				[]*sppb.StructType_Field{
1132					{Name: "Col0", Type: listType(timeType())},
1133				},
1134				[]*proto3.Value{{Kind: &proto3.Value_ListValue{}}},
1135			},
1136			&[]NullTime{},
1137			errDecodeColumn(0, errNilListValue("TIMESTAMP")),
1138		},
1139		{
1140			// Field specifies ARRAY<TIMESTAMP> type, but value is for FLOAT64 type.
1141			&Row{
1142				[]*sppb.StructType_Field{
1143					{Name: "Col0", Type: listType(timeType())},
1144				},
1145				[]*proto3.Value{floatProto(1.0)},
1146			},
1147			&[]NullTime{},
1148			errDecodeColumn(0, errSrcVal(floatProto(1.0), "List")),
1149		},
1150		{
1151			// Field specifies ARRAY<TIMESTAMP> type, but value is for ARRAY<FLOAT64> type.
1152			&Row{
1153				[]*sppb.StructType_Field{
1154					{Name: "Col0", Type: listType(timeType())},
1155				},
1156				[]*proto3.Value{listProto(floatProto(1.0))},
1157			},
1158			&[]NullTime{},
1159			errDecodeColumn(0, errDecodeArrayElement(0, floatProto(1.0),
1160				"TIMESTAMP", errSrcVal(floatProto(1.0), "String"))),
1161		},
1162		{
1163			// Field specifies ARRAY<DATE> type, value is having a nil Kind.
1164			&Row{
1165				[]*sppb.StructType_Field{
1166					{Name: "Col0", Type: listType(dateType())},
1167				},
1168				[]*proto3.Value{{Kind: (*proto3.Value_ListValue)(nil)}},
1169			},
1170			&[]NullDate{},
1171			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_ListValue)(nil)}, "List")),
1172		},
1173		{
1174			// Field specifies ARRAY<DATE> type, value is having a nil ListValue.
1175			&Row{
1176				[]*sppb.StructType_Field{
1177					{Name: "Col0", Type: listType(dateType())},
1178				},
1179				[]*proto3.Value{{Kind: &proto3.Value_ListValue{}}},
1180			},
1181			&[]NullDate{},
1182			errDecodeColumn(0, errNilListValue("DATE")),
1183		},
1184		{
1185			// Field specifies ARRAY<DATE> type, but value is for FLOAT64 type.
1186			&Row{
1187				[]*sppb.StructType_Field{
1188					{Name: "Col0", Type: listType(dateType())},
1189				},
1190				[]*proto3.Value{floatProto(1.0)},
1191			},
1192			&[]NullDate{},
1193			errDecodeColumn(0, errSrcVal(floatProto(1.0), "List")),
1194		},
1195		{
1196			// Field specifies ARRAY<DATE> type, but value is for ARRAY<FLOAT64> type.
1197			&Row{
1198				[]*sppb.StructType_Field{
1199					{Name: "Col0", Type: listType(dateType())},
1200				},
1201				[]*proto3.Value{listProto(floatProto(1.0))},
1202			},
1203			&[]NullDate{},
1204			errDecodeColumn(0, errDecodeArrayElement(0, floatProto(1.0),
1205				"DATE", errSrcVal(floatProto(1.0), "String"))),
1206		},
1207		{
1208			// Field specifies ARRAY<STRUCT> type, value is having a nil Kind.
1209			&Row{
1210				[]*sppb.StructType_Field{
1211					{Name: "Col0", Type: listType(structType(
1212						mkField("Col1", intType()),
1213						mkField("Col2", floatType()),
1214						mkField("Col3", stringType()),
1215					))},
1216				},
1217				[]*proto3.Value{{Kind: (*proto3.Value_ListValue)(nil)}},
1218			},
1219			&[]*struct {
1220				Col1 int64
1221				Col2 float64
1222				Col3 string
1223			}{},
1224			errDecodeColumn(0, errSrcVal(&proto3.Value{Kind: (*proto3.Value_ListValue)(nil)}, "List")),
1225		},
1226		{
1227			// Field specifies ARRAY<STRUCT> type, value is having a nil ListValue.
1228			&Row{
1229				[]*sppb.StructType_Field{
1230					{Name: "Col0", Type: listType(structType(
1231						mkField("Col1", intType()),
1232						mkField("Col2", floatType()),
1233						mkField("Col3", stringType()),
1234					))},
1235				},
1236				[]*proto3.Value{{Kind: &proto3.Value_ListValue{}}},
1237			},
1238			&[]*struct {
1239				Col1 int64
1240				Col2 float64
1241				Col3 string
1242			}{},
1243			errDecodeColumn(0, errNilListValue("STRUCT")),
1244		},
1245		{
1246			// Field specifies ARRAY<STRUCT> type, value is having a nil ListValue.
1247			&Row{
1248				[]*sppb.StructType_Field{
1249					{
1250						Name: "Col0",
1251						Type: listType(
1252							structType(
1253								mkField("Col1", intType()),
1254								mkField("Col2", floatType()),
1255								mkField("Col3", stringType()),
1256							),
1257						),
1258					},
1259				},
1260				[]*proto3.Value{{Kind: &proto3.Value_ListValue{}}},
1261			},
1262			&[]NullRow{},
1263			errDecodeColumn(0, errNilListValue("STRUCT")),
1264		},
1265		{
1266			// Field specifies ARRAY<STRUCT> type, value is for BYTES type.
1267			&Row{
1268				[]*sppb.StructType_Field{
1269					{
1270						Name: "Col0",
1271						Type: listType(
1272							structType(
1273								mkField("Col1", intType()),
1274								mkField("Col2", floatType()),
1275								mkField("Col3", stringType()),
1276							),
1277						),
1278					},
1279				},
1280				[]*proto3.Value{bytesProto([]byte("value"))},
1281			},
1282			&[]*struct {
1283				Col1 int64
1284				Col2 float64
1285				Col3 string
1286			}{},
1287			errDecodeColumn(0, errSrcVal(bytesProto([]byte("value")), "List")),
1288		},
1289		{
1290			// Field specifies ARRAY<STRUCT> type, value is for BYTES type.
1291			&Row{
1292				[]*sppb.StructType_Field{
1293					{
1294						Name: "Col0",
1295						Type: listType(
1296							structType(
1297								mkField("Col1", intType()),
1298								mkField("Col2", floatType()),
1299								mkField("Col3", stringType()),
1300							),
1301						),
1302					},
1303				},
1304				[]*proto3.Value{listProto(bytesProto([]byte("value")))},
1305			},
1306			&[]NullRow{},
1307			errDecodeColumn(0, errNotStructElement(0, bytesProto([]byte("value")))),
1308		},
1309		{
1310			// Field specifies ARRAY<STRUCT> type, value is for ARRAY<BYTES> type.
1311			&Row{
1312				[]*sppb.StructType_Field{
1313					{
1314						Name: "Col0",
1315						Type: listType(
1316							structType(
1317								mkField("Col1", intType()),
1318								mkField("Col2", floatType()),
1319								mkField("Col3", stringType()),
1320							),
1321						),
1322					},
1323				},
1324				[]*proto3.Value{listProto(bytesProto([]byte("value")))},
1325			},
1326			&[]*struct {
1327				Col1 int64
1328				Col2 float64
1329				Col3 string
1330			}{},
1331			errDecodeColumn(0, errDecodeArrayElement(0, bytesProto([]byte("value")),
1332				"STRUCT", errSrcVal(bytesProto([]byte("value")), "List"))),
1333		},
1334		{
1335			// Field specifies ARRAY<STRUCT>, but is having nil StructType.
1336			&Row{
1337				[]*sppb.StructType_Field{
1338					{
1339						Name: "Col0", Type: listType(&sppb.Type{Code: sppb.TypeCode_STRUCT}),
1340					},
1341				},
1342				[]*proto3.Value{listProto(listProto(intProto(1), floatProto(2.0), stringProto("3")))},
1343			},
1344			&[]*struct {
1345				Col1 int64
1346				Col2 float64
1347				Col3 string
1348			}{},
1349			errDecodeColumn(0, errDecodeArrayElement(0, listProto(intProto(1), floatProto(2.0), stringProto("3")),
1350				"STRUCT", errNilSpannerStructType())),
1351		},
1352		{
1353			// Field specifies ARRAY<STRUCT>, but the second struct value is for BOOL type instead of FLOAT64.
1354			&Row{
1355				[]*sppb.StructType_Field{
1356					{
1357						Name: "Col0",
1358						Type: listType(
1359							structType(
1360								mkField("Col1", intType()),
1361								mkField("Col2", floatType()),
1362								mkField("Col3", stringType()),
1363							),
1364						),
1365					},
1366				},
1367				[]*proto3.Value{listProto(listProto(intProto(1), boolProto(true), stringProto("3")))},
1368			},
1369			&[]*struct {
1370				Col1 int64
1371				Col2 float64
1372				Col3 string
1373			}{},
1374			errDecodeColumn(
1375				0,
1376				errDecodeArrayElement(
1377					0, listProto(intProto(1), boolProto(true), stringProto("3")), "STRUCT",
1378					errDecodeStructField(
1379						&sppb.StructType{
1380							Fields: []*sppb.StructType_Field{
1381								mkField("Col1", intType()),
1382								mkField("Col2", floatType()),
1383								mkField("Col3", stringType()),
1384							},
1385						},
1386						"Col2",
1387						errSrcVal(boolProto(true), "Number"),
1388					),
1389				),
1390			),
1391		},
1392	} {
1393		if gotErr := test.row.Column(0, test.dst); !testEqual(gotErr, test.wantErr) {
1394			t.Errorf("%v: test.row.Column(0) got error %v, want %v", i, gotErr, test.wantErr)
1395		}
1396		if gotErr := test.row.ColumnByName("Col0", test.dst); !testEqual(gotErr, test.wantErr) {
1397			t.Errorf("%v: test.row.ColumnByName(%q) got error %v, want %v", i, "Col0", gotErr, test.wantErr)
1398		}
1399		if gotErr := test.row.Columns(test.dst); !testEqual(gotErr, test.wantErr) {
1400			t.Errorf("%v: test.row.Columns(%T) got error %v, want %v", i, test.dst, gotErr, test.wantErr)
1401		}
1402	}
1403}
1404
1405// Test Row.ToStruct().
1406func TestToStruct(t *testing.T) {
1407	s := []struct {
1408		// STRING / STRING ARRAY
1409		PrimaryKey      string       `spanner:"STRING"`
1410		NullString      NullString   `spanner:"NULL_STRING"`
1411		StringArray     []NullString `spanner:"STRING_ARRAY"`
1412		NullStringArray []NullString `spanner:"NULL_STRING_ARRAY"`
1413		// BYTES / BYTES ARRAY
1414		Bytes          []byte   `spanner:"BYTES"`
1415		NullBytes      []byte   `spanner:"NULL_BYTES"`
1416		BytesArray     [][]byte `spanner:"BYTES_ARRAY"`
1417		NullBytesArray [][]byte `spanner:"NULL_BYTES_ARRAY"`
1418		// INT64 / INT64 ARRAY
1419		Int64          int64       `spanner:"INT64"`
1420		NullInt64      NullInt64   `spanner:"NULL_INT64"`
1421		Int64Array     []NullInt64 `spanner:"INT64_ARRAY"`
1422		NullInt64Array []NullInt64 `spanner:"NULL_INT64_ARRAY"`
1423		// BOOL / BOOL ARRAY
1424		Bool          bool       `spanner:"BOOL"`
1425		NullBool      NullBool   `spanner:"NULL_BOOL"`
1426		BoolArray     []NullBool `spanner:"BOOL_ARRAY"`
1427		NullBoolArray []NullBool `spanner:"NULL_BOOL_ARRAY"`
1428		// FLOAT64 / FLOAT64 ARRAY
1429		Float64          float64       `spanner:"FLOAT64"`
1430		NullFloat64      NullFloat64   `spanner:"NULL_FLOAT64"`
1431		Float64Array     []NullFloat64 `spanner:"FLOAT64_ARRAY"`
1432		NullFloat64Array []NullFloat64 `spanner:"NULL_FLOAT64_ARRAY"`
1433		// TIMESTAMP / TIMESTAMP ARRAY
1434		Timestamp          time.Time  `spanner:"TIMESTAMP"`
1435		NullTimestamp      NullTime   `spanner:"NULL_TIMESTAMP"`
1436		TimestampArray     []NullTime `spanner:"TIMESTAMP_ARRAY"`
1437		NullTimestampArray []NullTime `spanner:"NULL_TIMESTAMP_ARRAY"`
1438		// DATE / DATE ARRAY
1439		Date          civil.Date `spanner:"DATE"`
1440		NullDate      NullDate   `spanner:"NULL_DATE"`
1441		DateArray     []NullDate `spanner:"DATE_ARRAY"`
1442		NullDateArray []NullDate `spanner:"NULL_DATE_ARRAY"`
1443
1444		// STRUCT ARRAY
1445		StructArray []*struct {
1446			Col1 int64
1447			Col2 float64
1448			Col3 string
1449		} `spanner:"STRUCT_ARRAY"`
1450		NullStructArray []*struct {
1451			Col1 int64
1452			Col2 float64
1453			Col3 string
1454		} `spanner:"NULL_STRUCT_ARRAY"`
1455	}{
1456		{}, // got
1457		{
1458			// STRING / STRING ARRAY
1459			"value",
1460			NullString{},
1461			[]NullString{{"value1", true}, {}, {"value3", true}},
1462			[]NullString(nil),
1463			// BYTES / BYTES ARRAY
1464			[]byte("value"),
1465			[]byte(nil),
1466			[][]byte{[]byte("value1"), nil, []byte("value3")},
1467			[][]byte(nil),
1468			// INT64 / INT64 ARRAY
1469			int64(17),
1470			NullInt64{},
1471			[]NullInt64{{int64(1), true}, {int64(2), true}, {}},
1472			[]NullInt64(nil),
1473			// BOOL / BOOL ARRAY
1474			true,
1475			NullBool{},
1476			[]NullBool{{}, {true, true}, {false, true}},
1477			[]NullBool(nil),
1478			// FLOAT64 / FLOAT64 ARRAY
1479			1.7,
1480			NullFloat64{},
1481			[]NullFloat64{{}, {}, {1.7, true}},
1482			[]NullFloat64(nil),
1483			// TIMESTAMP / TIMESTAMP ARRAY
1484			tm,
1485			NullTime{},
1486			[]NullTime{{}, {tm, true}},
1487			[]NullTime(nil),
1488			// DATE / DATE ARRAY
1489			dt,
1490			NullDate{},
1491			[]NullDate{{}, {dt, true}},
1492			[]NullDate(nil),
1493			// STRUCT ARRAY
1494			[]*struct {
1495				Col1 int64
1496				Col2 float64
1497				Col3 string
1498			}{
1499				nil,
1500
1501				{3, 33.3, "three"},
1502				nil,
1503			},
1504			[]*struct {
1505				Col1 int64
1506				Col2 float64
1507				Col3 string
1508			}(nil),
1509		}, // want
1510	}
1511	err := row.ToStruct(&s[0])
1512	if err != nil {
1513		t.Errorf("row.ToStruct() returns error: %v, want nil", err)
1514	} else if !testEqual(s[0], s[1]) {
1515		t.Errorf("row.ToStruct() fetches struct %v, want %v", s[0], s[1])
1516	}
1517}
1518
1519// Test Row.ToStruct() with custom types.
1520func TestToStructWithCustomTypes(t *testing.T) {
1521	type CustomString string
1522	type CustomNullString NullString
1523	type CustomBytes []byte
1524	type CustomInt64 int64
1525	type CustomNullInt64 NullInt64
1526	type CustomBool bool
1527	type CustomNullBool NullBool
1528	type CustomFloat64 float64
1529	type CustomNullFloat64 NullFloat64
1530	type CustomTime time.Time
1531	type CustomNullTime NullTime
1532	type CustomDate civil.Date
1533	type CustomNullDate NullDate
1534
1535	s := []struct {
1536		// STRING / STRING ARRAY
1537		PrimaryKey      CustomString       `spanner:"STRING"`
1538		NullString      CustomNullString   `spanner:"NULL_STRING"`
1539		StringArray     []CustomNullString `spanner:"STRING_ARRAY"`
1540		NullStringArray []CustomNullString `spanner:"NULL_STRING_ARRAY"`
1541		// BYTES / BYTES ARRAY
1542		Bytes          CustomBytes   `spanner:"BYTES"`
1543		NullBytes      CustomBytes   `spanner:"NULL_BYTES"`
1544		BytesArray     []CustomBytes `spanner:"BYTES_ARRAY"`
1545		NullBytesArray []CustomBytes `spanner:"NULL_BYTES_ARRAY"`
1546		// INT64 / INT64 ARRAY
1547		Int64          CustomInt64       `spanner:"INT64"`
1548		NullInt64      CustomNullInt64   `spanner:"NULL_INT64"`
1549		Int64Array     []CustomNullInt64 `spanner:"INT64_ARRAY"`
1550		NullInt64Array []CustomNullInt64 `spanner:"NULL_INT64_ARRAY"`
1551		// BOOL / BOOL ARRAY
1552		Bool          CustomBool       `spanner:"BOOL"`
1553		NullBool      CustomNullBool   `spanner:"NULL_BOOL"`
1554		BoolArray     []CustomNullBool `spanner:"BOOL_ARRAY"`
1555		NullBoolArray []CustomNullBool `spanner:"NULL_BOOL_ARRAY"`
1556		// FLOAT64 / FLOAT64 ARRAY
1557		Float64          CustomFloat64       `spanner:"FLOAT64"`
1558		NullFloat64      CustomNullFloat64   `spanner:"NULL_FLOAT64"`
1559		Float64Array     []CustomNullFloat64 `spanner:"FLOAT64_ARRAY"`
1560		NullFloat64Array []CustomNullFloat64 `spanner:"NULL_FLOAT64_ARRAY"`
1561		// TIMESTAMP / TIMESTAMP ARRAY
1562		Timestamp          CustomTime       `spanner:"TIMESTAMP"`
1563		NullTimestamp      CustomNullTime   `spanner:"NULL_TIMESTAMP"`
1564		TimestampArray     []CustomNullTime `spanner:"TIMESTAMP_ARRAY"`
1565		NullTimestampArray []CustomNullTime `spanner:"NULL_TIMESTAMP_ARRAY"`
1566		// DATE / DATE ARRAY
1567		Date          CustomDate       `spanner:"DATE"`
1568		NullDate      CustomNullDate   `spanner:"NULL_DATE"`
1569		DateArray     []CustomNullDate `spanner:"DATE_ARRAY"`
1570		NullDateArray []CustomNullDate `spanner:"NULL_DATE_ARRAY"`
1571
1572		// STRUCT ARRAY
1573		StructArray []*struct {
1574			Col1 CustomInt64
1575			Col2 CustomFloat64
1576			Col3 CustomString
1577		} `spanner:"STRUCT_ARRAY"`
1578		NullStructArray []*struct {
1579			Col1 CustomInt64
1580			Col2 CustomFloat64
1581			Col3 CustomString
1582		} `spanner:"NULL_STRUCT_ARRAY"`
1583	}{
1584		{}, // got
1585		{
1586			// STRING / STRING ARRAY
1587			"value",
1588			CustomNullString{},
1589			[]CustomNullString{{"value1", true}, {}, {"value3", true}},
1590			[]CustomNullString(nil),
1591			// BYTES / BYTES ARRAY
1592			CustomBytes("value"),
1593			CustomBytes(nil),
1594			[]CustomBytes{[]byte("value1"), nil, []byte("value3")},
1595			[]CustomBytes(nil),
1596			// INT64 / INT64 ARRAY
1597			CustomInt64(17),
1598			CustomNullInt64{},
1599			[]CustomNullInt64{{int64(1), true}, {int64(2), true}, {}},
1600			[]CustomNullInt64(nil),
1601			// BOOL / BOOL ARRAY
1602			true,
1603			CustomNullBool{},
1604			[]CustomNullBool{{}, {true, true}, {false, true}},
1605			[]CustomNullBool(nil),
1606			// FLOAT64 / FLOAT64 ARRAY
1607			1.7,
1608			CustomNullFloat64{},
1609			[]CustomNullFloat64{{}, {}, {1.7, true}},
1610			[]CustomNullFloat64(nil),
1611			// TIMESTAMP / TIMESTAMP ARRAY
1612			CustomTime(tm),
1613			CustomNullTime{},
1614			[]CustomNullTime{{}, {tm, true}},
1615			[]CustomNullTime(nil),
1616			// DATE / DATE ARRAY
1617			CustomDate(dt),
1618			CustomNullDate{},
1619			[]CustomNullDate{{}, {dt, true}},
1620			[]CustomNullDate(nil),
1621			// STRUCT ARRAY
1622			[]*struct {
1623				Col1 CustomInt64
1624				Col2 CustomFloat64
1625				Col3 CustomString
1626			}{
1627				nil,
1628
1629				{3, 33.3, "three"},
1630				nil,
1631			},
1632			[]*struct {
1633				Col1 CustomInt64
1634				Col2 CustomFloat64
1635				Col3 CustomString
1636			}(nil),
1637		}, // want
1638	}
1639	err := row.ToStruct(&s[0])
1640	if err != nil {
1641		t.Errorf("row.ToStruct() returns error: %v, want nil", err)
1642	} else if !testutil.Equal(s[0], s[1], cmp.AllowUnexported(CustomTime{})) {
1643		t.Errorf("row.ToStruct() fetches struct %v, want %v", s[0], s[1])
1644	}
1645}
1646
1647func TestToStructEmbedded(t *testing.T) {
1648	type (
1649		S1 struct{ F1 string }
1650		S2 struct {
1651			S1
1652			F2 string
1653		}
1654	)
1655	r := Row{
1656		[]*sppb.StructType_Field{
1657			{Name: "F1", Type: stringType()},
1658			{Name: "F2", Type: stringType()},
1659		},
1660		[]*proto3.Value{
1661			stringProto("v1"),
1662			stringProto("v2"),
1663		},
1664	}
1665	var got S2
1666	if err := r.ToStruct(&got); err != nil {
1667		t.Fatal(err)
1668	}
1669	want := S2{S1: S1{F1: "v1"}, F2: "v2"}
1670	if !testEqual(got, want) {
1671		t.Errorf("got %+v, want %+v", got, want)
1672	}
1673}
1674
1675// Test helpers for getting column names.
1676func TestColumnNameAndIndex(t *testing.T) {
1677	// Test Row.Size().
1678	if rs := row.Size(); rs != len(row.fields) {
1679		t.Errorf("row.Size() returns %v, want %v", rs, len(row.fields))
1680	}
1681	// Test Row.Size() on empty Row.
1682	if rs := (&Row{}).Size(); rs != 0 {
1683		t.Errorf("empty_row.Size() returns %v, want %v", rs, 0)
1684	}
1685	// Test Row.ColumnName()
1686	for i, col := range row.fields {
1687		if cn := row.ColumnName(i); cn != col.Name {
1688			t.Errorf("row.ColumnName(%v) returns %q, want %q", i, cn, col.Name)
1689		}
1690		goti, err := row.ColumnIndex(col.Name)
1691		if err != nil {
1692			t.Errorf("ColumnIndex(%q) error %v", col.Name, err)
1693			continue
1694		}
1695		if goti != i {
1696			t.Errorf("ColumnIndex(%q) = %d, want %d", col.Name, goti, i)
1697		}
1698	}
1699	// Test Row.ColumnName on empty Row.
1700	if cn := (&Row{}).ColumnName(0); cn != "" {
1701		t.Errorf("empty_row.ColumnName(%v) returns %q, want %q", 0, cn, "")
1702	}
1703	// Test Row.ColumnIndex on empty Row.
1704	if _, err := (&Row{}).ColumnIndex(""); err == nil {
1705		t.Error("empty_row.ColumnIndex returns nil, want error")
1706	}
1707}
1708
1709func TestNewRow(t *testing.T) {
1710	for _, test := range []struct {
1711		names   []string
1712		values  []interface{}
1713		want    *Row
1714		wantErr error
1715	}{
1716		{
1717			want: &Row{fields: []*sppb.StructType_Field{}, vals: []*proto3.Value{}},
1718		},
1719		{
1720			names:  []string{},
1721			values: []interface{}{},
1722			want:   &Row{fields: []*sppb.StructType_Field{}, vals: []*proto3.Value{}},
1723		},
1724		{
1725			names:   []string{"a", "b"},
1726			values:  []interface{}{},
1727			want:    nil,
1728			wantErr: errNamesValuesMismatch([]string{"a", "b"}, []interface{}{}),
1729		},
1730		{
1731			names:  []string{"a", "b", "c"},
1732			values: []interface{}{5, "abc", GenericColumnValue{listType(intType()), listProto(intProto(91), nullProto(), intProto(87))}},
1733			want: &Row{
1734				[]*sppb.StructType_Field{
1735					{Name: "a", Type: intType()},
1736					{Name: "b", Type: stringType()},
1737					{Name: "c", Type: listType(intType())},
1738				},
1739				[]*proto3.Value{
1740					intProto(5),
1741					stringProto("abc"),
1742					listProto(intProto(91), nullProto(), intProto(87)),
1743				},
1744			},
1745		},
1746	} {
1747		got, err := NewRow(test.names, test.values)
1748		if !testEqual(err, test.wantErr) {
1749			t.Errorf("NewRow(%v,%v).err = %s, want %s", test.names, test.values, err, test.wantErr)
1750			continue
1751		}
1752		if !testEqual(got, test.want) {
1753			t.Errorf("NewRow(%v,%v) = %s, want %s", test.names, test.values, got, test.want)
1754			continue
1755		}
1756	}
1757}
1758
1759func BenchmarkColumn(b *testing.B) {
1760	var s string
1761	for i := 0; i < b.N; i++ {
1762		if err := row.Column(0, &s); err != nil {
1763			b.Fatal(err)
1764		}
1765	}
1766}
1767