@@ -986,7 +986,7 @@ func parseNullTime(v *proto3.Value, p *NullTime, code sppb.TypeCode, isNull bool
986986
987987// decodeValue decodes a protobuf Value into a pointer to a Go value, as
988988// specified by sppb.Type.
989- func decodeValue (v * proto3.Value , t * sppb.Type , ptr interface {}) error {
989+ func decodeValue (v * proto3.Value , t * sppb.Type , ptr interface {}, opts ... decodeOptions ) error {
990990 if v == nil {
991991 return errNilSrc ()
992992 }
@@ -1891,7 +1891,13 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}) error {
18911891 if err != nil {
18921892 return err
18931893 }
1894- if err = decodeStructArray (t .ArrayElementType .StructType , x , p ); err != nil {
1894+ s := decodeSetting {
1895+ Lenient : false ,
1896+ }
1897+ for _ , opt := range opts {
1898+ opt .Apply (& s )
1899+ }
1900+ if err = decodeStructArray (t .ArrayElementType .StructType , x , p , s .Lenient ); err != nil {
18951901 return err
18961902 }
18971903 }
@@ -3043,6 +3049,22 @@ func errDecodeStructField(ty *sppb.StructType, f string, err error) error {
30433049 return se
30443050}
30453051
3052+ // decodeSetting contains all the settings for decoding from spanner struct
3053+ type decodeSetting struct {
3054+ Lenient bool
3055+ }
3056+
3057+ // decodeOptions is the interface to change decode struct settings
3058+ type decodeOptions interface {
3059+ Apply (s * decodeSetting )
3060+ }
3061+
3062+ type withLenient struct { lenient bool }
3063+
3064+ func (w withLenient ) Apply (s * decodeSetting ) {
3065+ s .Lenient = w .lenient
3066+ }
3067+
30463068// decodeStruct decodes proto3.ListValue pb into struct referenced by pointer
30473069// ptr, according to
30483070// the structural information given in sppb.StructType ty.
@@ -3087,8 +3109,9 @@ func decodeStruct(ty *sppb.StructType, pb *proto3.ListValue, ptr interface{}, le
30873109 // We don't allow duplicated field name.
30883110 return errDupSpannerField (f .Name , ty )
30893111 }
3112+ opts := []decodeOptions {withLenient {lenient : lenient }}
30903113 // Try to decode a single field.
3091- if err := decodeValue (pb .Values [i ], f .Type , v .FieldByIndex (sf .Index ).Addr ().Interface ()); err != nil {
3114+ if err := decodeValue (pb .Values [i ], f .Type , v .FieldByIndex (sf .Index ).Addr ().Interface (), opts ... ); err != nil {
30923115 return errDecodeStructField (ty , f .Name , err )
30933116 }
30943117 // Mark field f.Name as processed.
@@ -3113,7 +3136,7 @@ func isPtrStructPtrSlice(t reflect.Type) bool {
31133136// decodeStructArray decodes proto3.ListValue pb into struct slice referenced by
31143137// pointer ptr, according to the
31153138// structural information given in a sppb.StructType.
3116- func decodeStructArray (ty * sppb.StructType , pb * proto3.ListValue , ptr interface {}) error {
3139+ func decodeStructArray (ty * sppb.StructType , pb * proto3.ListValue , ptr interface {}, lenient bool ) error {
31173140 if pb == nil {
31183141 return errNilListValue ("STRUCT" )
31193142 }
@@ -3139,7 +3162,7 @@ func decodeStructArray(ty *sppb.StructType, pb *proto3.ListValue, ptr interface{
31393162 return errDecodeArrayElement (i , pv , "STRUCT" , err )
31403163 }
31413164 // Decode proto3.ListValue l into struct referenced by s.Interface().
3142- if err = decodeStruct (ty , l , s .Interface (), false ); err != nil {
3165+ if err = decodeStruct (ty , l , s .Interface (), lenient ); err != nil {
31433166 return errDecodeArrayElement (i , pv , "STRUCT" , err )
31443167 }
31453168 // Append the decoded struct back into the slice.
0 commit comments