MCPcopy Create free account
hub / github.com/bytebase/bytebase / convertSpannerValue

Function convertSpannerValue

backend/plugin/db/spanner/spanner.go:446–550  ·  view source on GitHub ↗

convertSpannerValue converts google.protobuf.Value to RowValue. Uses type metadata to preserve INT64 precision and properly handle all Spanner types.

(colType *sppb.Type, v *structpb.Value)

Source from the content-addressed store, hash-verified

444// convertSpannerValue converts google.protobuf.Value to RowValue.
445// Uses type metadata to preserve INT64 precision and properly handle all Spanner types.
446func convertSpannerValue(colType *sppb.Type, v *structpb.Value) *v1pb.RowValue {
447 if v == nil || v.Kind == nil {
448 return util.NullRowValue
449 }
450
451 switch v.Kind.(type) {
452 case *structpb.Value_NullValue:
453 return util.NullRowValue
454 case *structpb.Value_StringValue:
455 stringValue := v.GetStringValue()
456 if colType == nil {
457 return &v1pb.RowValue{Kind: &v1pb.RowValue_StringValue{
458 StringValue: stringValue,
459 }}
460 }
461
462 switch colType.Code {
463 case sppb.TypeCode_INT64:
464 // Spanner encodes INT64 as strings to preserve precision
465 val, err := strconv.ParseInt(stringValue, 10, 64)
466 if err != nil {
467 slog.Error("failed to parse INT64 string value", log.BBError(err))
468 return &v1pb.RowValue{Kind: &v1pb.RowValue_StringValue{
469 StringValue: stringValue,
470 }}
471 }
472 return &v1pb.RowValue{Kind: &v1pb.RowValue_Int64Value{
473 Int64Value: val,
474 }}
475 case sppb.TypeCode_TIMESTAMP:
476 // Spanner encodes TIMESTAMP as RFC3339 string with nanosecond precision
477 t, err := time.Parse(time.RFC3339Nano, stringValue)
478 if err != nil {
479 slog.Error("failed to parse TIMESTAMP string value", log.BBError(err))
480 return &v1pb.RowValue{Kind: &v1pb.RowValue_StringValue{
481 StringValue: stringValue,
482 }}
483 }
484 // Determine accuracy from the string
485 accuracy := int32(6) // Default to microsecond precision
486 if dotIndex := strings.Index(stringValue, "."); dotIndex >= 0 {
487 // Find the end of fractional seconds (before 'Z' or timezone)
488 endIndex := strings.IndexAny(stringValue[dotIndex:], "Z+-")
489 if endIndex > 0 {
490 accuracy = int32(endIndex - 1)
491 if accuracy > 9 {
492 accuracy = 9 // Cap at nanosecond precision
493 }
494 }
495 }
496 return &v1pb.RowValue{Kind: &v1pb.RowValue_TimestampValue{
497 TimestampValue: &v1pb.RowValue_Timestamp{
498 GoogleTimestamp: timestamppb.New(t),
499 Accuracy: accuracy,
500 },
501 }}
502 case sppb.TypeCode_BYTES:
503 // Spanner encodes BYTES as base64 string

Callers 2

TestConvertSpannerValueFunction · 0.85
readRowFunction · 0.85

Calls 4

BBErrorFunction · 0.92
GetStringValueMethod · 0.80
GetBoolValueMethod · 0.80
ErrorMethod · 0.45

Tested by 1

TestConvertSpannerValueFunction · 0.68