@@ -64,6 +64,7 @@ type rows struct {
6464 colsOnce sync.Once
6565 dirtyErr error
6666 cols []string
67+ colTypes []* sppb.Type
6768
6869 state * connectionstate.ConnectionState
6970 decodeOption DecodeOption
@@ -155,8 +156,10 @@ func (r *rows) getColumns() {
155156 }
156157 rowType := metadata .RowType
157158 r .cols = make ([]string , len (rowType .Fields ))
159+ r .colTypes = make ([]* sppb.Type , len (rowType .Fields ))
158160 for i , c := range rowType .Fields {
159161 r .cols [i ] = c .Name
162+ r .colTypes [i ] = c .Type
160163 }
161164 })
162165}
@@ -203,19 +206,23 @@ func (r *rows) Next(dest []driver.Value) error {
203206 }
204207 }
205208
209+ if r .colTypes == nil {
210+ return fmt .Errorf ("spanner: missing column types metadata" )
211+ }
212+
206213 for i := 0 ; i < row .Size (); i ++ {
207- var col spanner.GenericColumnValue
208- if err := row .Column (i , & col ); err != nil {
209- return err
210- }
211214 if r .decodeOption == DecodeOptionProto {
215+ var col spanner.GenericColumnValue
216+ if err := row .Column (i , & col ); err != nil {
217+ return err
218+ }
212219 dest [i ] = col
213220 continue
214221 }
215- switch col . Type .Code {
222+ switch r . colTypes [ i ] .Code {
216223 case sppb .TypeCode_INT64 , sppb .TypeCode_ENUM :
217224 var v spanner.NullInt64
218- if err := col . Decode ( & v ); err != nil {
225+ if err := row . Column ( i , & v ); err != nil {
219226 return err
220227 }
221228 if v .Valid {
@@ -225,7 +232,7 @@ func (r *rows) Next(dest []driver.Value) error {
225232 }
226233 case sppb .TypeCode_FLOAT32 :
227234 var v spanner.NullFloat32
228- if err := col . Decode ( & v ); err != nil {
235+ if err := row . Column ( i , & v ); err != nil {
229236 return err
230237 }
231238 if v .Valid {
@@ -235,7 +242,7 @@ func (r *rows) Next(dest []driver.Value) error {
235242 }
236243 case sppb .TypeCode_FLOAT64 :
237244 var v spanner.NullFloat64
238- if err := col . Decode ( & v ); err != nil {
245+ if err := row . Column ( i , & v ); err != nil {
239246 return err
240247 }
241248 if v .Valid {
@@ -245,15 +252,19 @@ func (r *rows) Next(dest []driver.Value) error {
245252 }
246253 case sppb .TypeCode_NUMERIC :
247254 if propertyDecodeNumericToString .GetValueOrDefault (r .state ) {
255+ var col spanner.GenericColumnValue
256+ if err := row .Column (i , & col ); err != nil {
257+ return err
258+ }
248259 if _ , ok := col .Value .Kind .(* structpb.Value_NullValue ); ok {
249260 dest [i ] = nil
250261 } else {
251262 dest [i ] = col .Value .GetStringValue ()
252263 }
253264 } else {
254- if col . Type .TypeAnnotation == sppb .TypeAnnotationCode_PG_NUMERIC {
265+ if r . colTypes [ i ] .TypeAnnotation == sppb .TypeAnnotationCode_PG_NUMERIC {
255266 var v spanner.PGNumeric
256- if err := col . Decode ( & v ); err != nil {
267+ if err := row . Column ( i , & v ); err != nil {
257268 return err
258269 }
259270 if v .Valid {
@@ -263,7 +274,7 @@ func (r *rows) Next(dest []driver.Value) error {
263274 }
264275 } else {
265276 var v spanner.NullNumeric
266- if err := col . Decode ( & v ); err != nil {
277+ if err := row . Column ( i , & v ); err != nil {
267278 return err
268279 }
269280 if v .Valid {
@@ -275,7 +286,7 @@ func (r *rows) Next(dest []driver.Value) error {
275286 }
276287 case sppb .TypeCode_STRING :
277288 var v spanner.NullString
278- if err := col . Decode ( & v ); err != nil {
289+ if err := row . Column ( i , & v ); err != nil {
279290 return err
280291 }
281292 if v .Valid {
@@ -284,15 +295,15 @@ func (r *rows) Next(dest []driver.Value) error {
284295 dest [i ] = nil
285296 }
286297 case sppb .TypeCode_JSON :
287- if col . Type .TypeAnnotation == sppb .TypeAnnotationCode_PG_JSONB {
298+ if r . colTypes [ i ] .TypeAnnotation == sppb .TypeAnnotationCode_PG_JSONB {
288299 var v spanner.PGJsonB
289- if err := col . Decode ( & v ); err != nil {
300+ if err := row . Column ( i , & v ); err != nil {
290301 return err
291302 }
292303 dest [i ] = v
293304 } else {
294305 var v spanner.NullJSON
295- if err := col . Decode ( & v ); err != nil {
306+ if err := row . Column ( i , & v ); err != nil {
296307 return err
297308 }
298309 // We always assign `v` to dest[i] here because there is no native type
@@ -302,7 +313,7 @@ func (r *rows) Next(dest []driver.Value) error {
302313 }
303314 case sppb .TypeCode_UUID :
304315 var v spanner.NullUUID
305- if err := col . Decode ( & v ); err != nil {
316+ if err := row . Column ( i , & v ); err != nil {
306317 return err
307318 }
308319 if v .Valid {
@@ -313,13 +324,13 @@ func (r *rows) Next(dest []driver.Value) error {
313324 case sppb .TypeCode_BYTES , sppb .TypeCode_PROTO :
314325 // The column value is a base64 encoded string.
315326 var v []byte
316- if err := col . Decode ( & v ); err != nil {
327+ if err := row . Column ( i , & v ); err != nil {
317328 return err
318329 }
319330 dest [i ] = v
320331 case sppb .TypeCode_BOOL :
321332 var v spanner.NullBool
322- if err := col . Decode ( & v ); err != nil {
333+ if err := row . Column ( i , & v ); err != nil {
323334 return err
324335 }
325336 if v .Valid {
@@ -328,15 +339,18 @@ func (r *rows) Next(dest []driver.Value) error {
328339 dest [i ] = nil
329340 }
330341 case sppb .TypeCode_DATE :
331- _ , isNull := col .Value .Kind .(* structpb.Value_NullValue )
332- if isNull {
342+ var col spanner.GenericColumnValue
343+ if err := row .Column (i , & col ); err != nil {
344+ return err
345+ }
346+ if _ , ok := col .Value .Kind .(* structpb.Value_NullValue ); ok {
333347 dest [i ] = nil
334348 } else {
335349 dest [i ] = col .Value .GetStringValue ()
336350 }
337351 case sppb .TypeCode_TIMESTAMP :
338352 var v spanner.NullTime
339- if err := col . Decode ( & v ); err != nil {
353+ if err := row . Column ( i , & v ); err != nil {
340354 return err
341355 }
342356 if v .Valid {
@@ -345,85 +359,85 @@ func (r *rows) Next(dest []driver.Value) error {
345359 dest [i ] = nil
346360 }
347361 case sppb .TypeCode_ARRAY :
348- switch col . Type .ArrayElementType .Code {
362+ switch r . colTypes [ i ] .ArrayElementType .Code {
349363 case sppb .TypeCode_INT64 , sppb .TypeCode_ENUM :
350364 if r .decodeToNativeArrays {
351365 var v []int64
352- if err := col . Decode ( & v ); err != nil {
366+ if err := row . Column ( i , & v ); err != nil {
353367 return err
354368 }
355369 dest [i ] = v
356370 } else {
357371 var v []spanner.NullInt64
358- if err := col . Decode ( & v ); err != nil {
372+ if err := row . Column ( i , & v ); err != nil {
359373 return err
360374 }
361375 dest [i ] = v
362376 }
363377 case sppb .TypeCode_FLOAT32 :
364378 if r .decodeToNativeArrays {
365379 var v []float32
366- if err := col . Decode ( & v ); err != nil {
380+ if err := row . Column ( i , & v ); err != nil {
367381 return err
368382 }
369383 dest [i ] = v
370384 } else {
371385 var v []spanner.NullFloat32
372- if err := col . Decode ( & v ); err != nil {
386+ if err := row . Column ( i , & v ); err != nil {
373387 return err
374388 }
375389 dest [i ] = v
376390 }
377391 case sppb .TypeCode_FLOAT64 :
378392 if r .decodeToNativeArrays {
379393 var v []float64
380- if err := col . Decode ( & v ); err != nil {
394+ if err := row . Column ( i , & v ); err != nil {
381395 return err
382396 }
383397 dest [i ] = v
384398 } else {
385399 var v []spanner.NullFloat64
386- if err := col . Decode ( & v ); err != nil {
400+ if err := row . Column ( i , & v ); err != nil {
387401 return err
388402 }
389403 dest [i ] = v
390404 }
391405 case sppb .TypeCode_NUMERIC :
392- if col . Type .ArrayElementType .TypeAnnotation == sppb .TypeAnnotationCode_PG_NUMERIC {
406+ if r . colTypes [ i ] .ArrayElementType .TypeAnnotation == sppb .TypeAnnotationCode_PG_NUMERIC {
393407 var v []spanner.PGNumeric
394- if err := col . Decode ( & v ); err != nil {
408+ if err := row . Column ( i , & v ); err != nil {
395409 return err
396410 }
397411 dest [i ] = v
398412 } else {
399413 var v []spanner.NullNumeric
400- if err := col . Decode ( & v ); err != nil {
414+ if err := row . Column ( i , & v ); err != nil {
401415 return err
402416 }
403417 dest [i ] = v
404418 }
405419 case sppb .TypeCode_STRING :
406420 if r .decodeToNativeArrays {
407421 var v []string
408- if err := col . Decode ( & v ); err != nil {
422+ if err := row . Column ( i , & v ); err != nil {
409423 return err
410424 }
411425 dest [i ] = v
412426 } else {
413427 var v []spanner.NullString
414- if err := col . Decode ( & v ); err != nil {
428+ if err := row . Column ( i , & v ); err != nil {
415429 return err
416430 }
417431 dest [i ] = v
418432 }
419433 case sppb .TypeCode_JSON :
420- if col . Type .ArrayElementType .TypeAnnotation == sppb .TypeAnnotationCode_PG_JSONB {
434+ if r . colTypes [ i ] .ArrayElementType .TypeAnnotation == sppb .TypeAnnotationCode_PG_JSONB {
421435 var v []spanner.PGJsonB
422- if err := col . Decode ( & v ); err != nil {
436+ if err := row . Column ( i , & v ); err != nil {
423437 // Workaround for https://github.com/googleapis/google-cloud-go/pull/13602
424438 if spanner .ErrCode (err ) == codes .InvalidArgument && err .Error () == "spanner: code = \" InvalidArgument\" , desc = \" type *[]spanner.PGJsonB cannot be used for decoding ARRAY[JSON]\" " {
425439 var tmp []spanner.NullJSON
426- if err := col . Decode ( & tmp ); err != nil {
440+ if err := row . Column ( i , & tmp ); err != nil {
427441 return err
428442 }
429443 v = make ([]spanner.PGJsonB , 0 , len (tmp ))
@@ -437,82 +451,82 @@ func (r *rows) Next(dest []driver.Value) error {
437451 dest [i ] = v
438452 } else {
439453 var v []spanner.NullJSON
440- if err := col . Decode ( & v ); err != nil {
454+ if err := row . Column ( i , & v ); err != nil {
441455 return err
442456 }
443457 dest [i ] = v
444458 }
445459 case sppb .TypeCode_UUID :
446460 if r .decodeToNativeArrays {
447461 var v []uuid.UUID
448- if err := col . Decode ( & v ); err != nil {
462+ if err := row . Column ( i , & v ); err != nil {
449463 return err
450464 }
451465 dest [i ] = v
452466 } else {
453467 var v []spanner.NullUUID
454- if err := col . Decode ( & v ); err != nil {
468+ if err := row . Column ( i , & v ); err != nil {
455469 return err
456470 }
457471 dest [i ] = v
458472 }
459473 case sppb .TypeCode_BYTES , sppb .TypeCode_PROTO :
460474 var v [][]byte
461- if err := col . Decode ( & v ); err != nil {
475+ if err := row . Column ( i , & v ); err != nil {
462476 return err
463477 }
464478 dest [i ] = v
465479 case sppb .TypeCode_BOOL :
466480 if r .decodeToNativeArrays {
467481 var v []bool
468- if err := col . Decode ( & v ); err != nil {
482+ if err := row . Column ( i , & v ); err != nil {
469483 return err
470484 }
471485 dest [i ] = v
472486 } else {
473487 var v []spanner.NullBool
474- if err := col . Decode ( & v ); err != nil {
488+ if err := row . Column ( i , & v ); err != nil {
475489 return err
476490 }
477491 dest [i ] = v
478492 }
479493 case sppb .TypeCode_DATE :
480494 if r .decodeToNativeArrays {
481495 var v []civil.Date
482- if err := col . Decode ( & v ); err != nil {
496+ if err := row . Column ( i , & v ); err != nil {
483497 return err
484498 }
485499 dest [i ] = v
486500 } else {
487501 var v []spanner.NullDate
488- if err := col . Decode ( & v ); err != nil {
502+ if err := row . Column ( i , & v ); err != nil {
489503 return err
490504 }
491505 dest [i ] = v
492506 }
493507 case sppb .TypeCode_TIMESTAMP :
494508 if r .decodeToNativeArrays {
495509 var v []time.Time
496- if err := col . Decode ( & v ); err != nil {
510+ if err := row . Column ( i , & v ); err != nil {
497511 return err
498512 }
499513 dest [i ] = v
500514 } else {
501515 var v []spanner.NullTime
502- if err := col . Decode ( & v ); err != nil {
516+ if err := row . Column ( i , & v ); err != nil {
503517 return err
504518 }
505519 dest [i ] = v
506520 }
507521 default :
508522 return fmt .Errorf ("unsupported array element type ARRAY<%v>, " +
509523 "use spannerdriver.ExecOptions{DecodeOption: spannerdriver.DecodeOptionProto} " +
510- "to return the underlying protobuf value" , col . Type .ArrayElementType .Code )
524+ "to return the underlying protobuf value" , r . colTypes [ i ] .ArrayElementType .Code )
511525 }
512526 default :
513527 return fmt .Errorf ("unsupported type %v, " +
514528 "use spannerdriver.ExecOptions{DecodeOption: spannerdriver.DecodeOptionProto} " +
515- "to return the underlying protobuf value" , col . Type .Code )
529+ "to return the underlying protobuf value" , r . colTypes [ i ] .Code )
516530 }
517531 }
518532 return nil
0 commit comments