From 6cd6a73be87a261729d3b6b45f3d28be93c3fdb3 Mon Sep 17 00:00:00 2001 From: Yuki Abe <12268087+yukia3e@users.noreply.github.com> Date: Fri, 23 Feb 2024 14:23:07 +0900 Subject: [PATCH] feat(spanner): SelectAll struct spanner tag annotation match should be case-insensitive (#9460) * feat(spanner): SelectAll struct spanner tag annotation match should be case-insensitive * feat(spanner): Add a test case (#9460) --- spanner/row.go | 4 ++-- spanner/row_test.go | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/spanner/row.go b/spanner/row.go index 1f541a1858a3..d546f240724e 100644 --- a/spanner/row.go +++ b/spanner/row.go @@ -566,8 +566,8 @@ func initFieldTag(sliceItem reflect.Value, fieldTagMap *map[string]reflect.Value continue } if name == "" { - name = strings.ToLower(fieldType.Name) + name = fieldType.Name } - (*fieldTagMap)[name] = sliceItem.Field(i) + (*fieldTagMap)[strings.ToLower(name)] = sliceItem.Field(i) } } diff --git a/spanner/row_test.go b/spanner/row_test.go index 87d795bdb0e6..466c9d5626b1 100644 --- a/spanner/row_test.go +++ b/spanner/row_test.go @@ -2008,6 +2008,12 @@ func TestSelectAll(t *testing.T) { Col3 string Col4 time.Time } + type testStructWithTag struct { + Col1 int64 `spanner:"tag1"` + Col2 float64 `spanner:"Tag2"` + Col3 string `spanner:"taG3"` + Col4 time.Time `spanner:"TAG4"` + } tests := []struct { name string args args @@ -2175,7 +2181,40 @@ func TestSelectAll(t *testing.T) { {Col1: 3, COL2: 3.3, Col3: "value3"}, {Col1: 1, COL2: 1.1, Col3: "value"}, {Col1: 2, COL2: 2.2, Col3: "value2"}, - }}, + }, + }, + { + name: "success: using slice of structs with spanner tag annotations", + args: args{ + destination: &[]testStructWithTag{}, + mock: func(mockIterator *mockRowIterator) { + mockIterator.On("Next").Once().Return(&Row{ + []*sppb.StructType_Field{ + {Name: "Tag1", Type: intType()}, + {Name: "Tag2", Type: floatType()}, + {Name: "Tag3", Type: stringType()}, + {Name: "Tag4", Type: timeType()}, + }, + []*proto3.Value{intProto(1), floatProto(1.1), stringProto("value"), timeProto(tm)}, + }, nil) + mockIterator.On("Next").Once().Return(&Row{ + []*sppb.StructType_Field{ + {Name: "Tag1", Type: intType()}, + {Name: "Tag2", Type: floatType()}, + {Name: "Tag3", Type: stringType()}, + {Name: "Tag4", Type: timeType()}, + }, + []*proto3.Value{intProto(2), floatProto(2.2), stringProto("value2"), timeProto(tm.Add(24 * time.Hour))}, + }, nil) + mockIterator.On("Next").Once().Return(nil, iterator.Done) + mockIterator.On("Stop").Once().Return(nil) + }, + }, + want: &[]testStructWithTag{ + {Col1: 1, Col2: 1.1, Col3: "value", Col4: tm}, + {Col1: 2, Col2: 2.2, Col3: "value2", Col4: tm.Add(24 * time.Hour)}, + }, + }, { name: "failure: in case of error destination will have the partial result", args: args{