@@ -2840,61 +2840,75 @@ private Status processResults(
2840
2840
/** Convert a result row to a row proto(value list) for sending back to the client. */
2841
2841
private com .google .spanner .executor .v1 .ValueList buildRow (
2842
2842
StructReader result , OutcomeSender sender ) throws SpannerException {
2843
- com .google .spanner .executor .v1 .ValueList .Builder rowBuilder =
2844
- com .google .spanner .executor .v1 .ValueList .newBuilder ();
2843
+ sender .setRowType (buildStructType (result ));
2844
+ return buildStruct (result );
2845
+ }
2846
+
2847
+ /** Construct a StructType for a given struct. This is used to set the row type. */
2848
+ private com .google .spanner .v1 .StructType buildStructType (StructReader struct ) {
2845
2849
com .google .spanner .v1 .StructType .Builder rowTypeBuilder =
2846
- com .google .spanner .v1 .StructType .newBuilder ();
2847
- for (int i = 0 ; i < result .getColumnCount (); ++i ) {
2848
- com .google .cloud .spanner .Type columnType = result .getColumnType (i );
2850
+ com .google .spanner .v1 .StructType .newBuilder ();
2851
+ for (int i = 0 ; i < struct .getColumnCount (); ++i ) {
2852
+ com .google .cloud .spanner .Type columnType = struct .getColumnType (i );
2849
2853
rowTypeBuilder .addFields (
2850
- com .google .spanner .v1 .StructType .Field .newBuilder ()
2851
- .setName (result .getType ().getStructFields ().get (i ).getName ())
2852
- .setType (cloudTypeToTypeProto (columnType ))
2853
- .build ());
2854
+ com .google .spanner .v1 .StructType .Field .newBuilder ()
2855
+ .setName (struct .getType ().getStructFields ().get (i ).getName ())
2856
+ .setType (cloudTypeToTypeProto (columnType ))
2857
+ .build ());
2858
+ }
2859
+ return rowTypeBuilder .build ();
2860
+ }
2861
+
2862
+ /** Convert a struct to a proto(value list) for constructing result rows and struct values. */
2863
+ private com .google .spanner .executor .v1 .ValueList buildStruct (StructReader struct ) {
2864
+ com .google .spanner .executor .v1 .ValueList .Builder structBuilder =
2865
+ com .google .spanner .executor .v1 .ValueList .newBuilder ();
2866
+ for (int i = 0 ; i < struct .getColumnCount (); ++i ) {
2867
+ com .google .cloud .spanner .Type columnType = struct .getColumnType (i );
2854
2868
com .google .spanner .executor .v1 .Value .Builder value =
2855
2869
com .google .spanner .executor .v1 .Value .newBuilder ();
2856
- if (result .isNull (i )) {
2870
+ if (struct .isNull (i )) {
2857
2871
value .setIsNull (true );
2858
2872
} else {
2859
2873
switch (columnType .getCode ()) {
2860
2874
case BOOL :
2861
- value .setBoolValue (result .getBoolean (i ));
2875
+ value .setBoolValue (struct .getBoolean (i ));
2862
2876
break ;
2863
2877
case FLOAT32 :
2864
- value .setDoubleValue ((double ) result .getFloat (i ));
2878
+ value .setDoubleValue ((double ) struct .getFloat (i ));
2865
2879
break ;
2866
2880
case FLOAT64 :
2867
- value .setDoubleValue (result .getDouble (i ));
2881
+ value .setDoubleValue (struct .getDouble (i ));
2868
2882
break ;
2869
2883
case INT64 :
2870
- value .setIntValue (result .getLong (i ));
2884
+ value .setIntValue (struct .getLong (i ));
2871
2885
break ;
2872
2886
case STRING :
2873
- value .setStringValue (result .getString (i ));
2887
+ value .setStringValue (struct .getString (i ));
2874
2888
break ;
2875
2889
case BYTES :
2876
- value .setBytesValue (toByteString (result .getBytes (i )));
2890
+ value .setBytesValue (toByteString (struct .getBytes (i )));
2877
2891
break ;
2878
2892
case TIMESTAMP :
2879
- value .setTimestampValue (timestampToProto (result .getTimestamp (i )));
2893
+ value .setTimestampValue (timestampToProto (struct .getTimestamp (i )));
2880
2894
break ;
2881
2895
case DATE :
2882
- value .setDateDaysValue (daysFromDate (result .getDate (i )));
2896
+ value .setDateDaysValue (daysFromDate (struct .getDate (i )));
2883
2897
break ;
2884
2898
case NUMERIC :
2885
- String ascii = result .getBigDecimal (i ).toPlainString ();
2899
+ String ascii = struct .getBigDecimal (i ).toPlainString ();
2886
2900
value .setStringValue (ascii );
2887
2901
break ;
2888
2902
case JSON :
2889
- value .setStringValue (result .getJson (i ));
2903
+ value .setStringValue (struct .getJson (i ));
2890
2904
break ;
2891
2905
case ARRAY :
2892
- switch (result .getColumnType (i ).getArrayElementType ().getCode ()) {
2906
+ switch (struct .getColumnType (i ).getArrayElementType ().getCode ()) {
2893
2907
case BOOL :
2894
2908
{
2895
2909
com .google .spanner .executor .v1 .ValueList .Builder builder =
2896
2910
com .google .spanner .executor .v1 .ValueList .newBuilder ();
2897
- List <Boolean > values = result .getBooleanList (i );
2911
+ List <Boolean > values = struct .getBooleanList (i );
2898
2912
for (Boolean booleanValue : values ) {
2899
2913
com .google .spanner .executor .v1 .Value .Builder valueProto =
2900
2914
com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2913,7 +2927,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
2913
2927
{
2914
2928
com .google .spanner .executor .v1 .ValueList .Builder builder =
2915
2929
com .google .spanner .executor .v1 .ValueList .newBuilder ();
2916
- List <Float > values = result .getFloatList (i );
2930
+ List <Float > values = struct .getFloatList (i );
2917
2931
for (Float floatValue : values ) {
2918
2932
com .google .spanner .executor .v1 .Value .Builder valueProto =
2919
2933
com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2932,7 +2946,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
2932
2946
{
2933
2947
com .google .spanner .executor .v1 .ValueList .Builder builder =
2934
2948
com .google .spanner .executor .v1 .ValueList .newBuilder ();
2935
- List <Double > values = result .getDoubleList (i );
2949
+ List <Double > values = struct .getDoubleList (i );
2936
2950
for (Double doubleValue : values ) {
2937
2951
com .google .spanner .executor .v1 .Value .Builder valueProto =
2938
2952
com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2951,7 +2965,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
2951
2965
{
2952
2966
com .google .spanner .executor .v1 .ValueList .Builder builder =
2953
2967
com .google .spanner .executor .v1 .ValueList .newBuilder ();
2954
- List <Long > values = result .getLongList (i );
2968
+ List <Long > values = struct .getLongList (i );
2955
2969
for (Long longValue : values ) {
2956
2970
com .google .spanner .executor .v1 .Value .Builder valueProto =
2957
2971
com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2970,7 +2984,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
2970
2984
{
2971
2985
com .google .spanner .executor .v1 .ValueList .Builder builder =
2972
2986
com .google .spanner .executor .v1 .ValueList .newBuilder ();
2973
- List <String > values = result .getStringList (i );
2987
+ List <String > values = struct .getStringList (i );
2974
2988
for (String stringValue : values ) {
2975
2989
com .google .spanner .executor .v1 .Value .Builder valueProto =
2976
2990
com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2989,7 +3003,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
2989
3003
{
2990
3004
com .google .spanner .executor .v1 .ValueList .Builder builder =
2991
3005
com .google .spanner .executor .v1 .ValueList .newBuilder ();
2992
- List <ByteArray > values = result .getBytesList (i );
3006
+ List <ByteArray > values = struct .getBytesList (i );
2993
3007
for (ByteArray byteArrayValue : values ) {
2994
3008
com .google .spanner .executor .v1 .Value .Builder valueProto =
2995
3009
com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3011,7 +3025,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
3011
3025
{
3012
3026
com .google .spanner .executor .v1 .ValueList .Builder builder =
3013
3027
com .google .spanner .executor .v1 .ValueList .newBuilder ();
3014
- List <Date > values = result .getDateList (i );
3028
+ List <Date > values = struct .getDateList (i );
3015
3029
for (Date dateValue : values ) {
3016
3030
com .google .spanner .executor .v1 .Value .Builder valueProto =
3017
3031
com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3031,7 +3045,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
3031
3045
{
3032
3046
com .google .spanner .executor .v1 .ValueList .Builder builder =
3033
3047
com .google .spanner .executor .v1 .ValueList .newBuilder ();
3034
- List <Timestamp > values = result .getTimestampList (i );
3048
+ List <Timestamp > values = struct .getTimestampList (i );
3035
3049
for (Timestamp timestampValue : values ) {
3036
3050
com .google .spanner .executor .v1 .Value .Builder valueProto =
3037
3051
com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3051,7 +3065,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
3051
3065
{
3052
3066
com .google .spanner .executor .v1 .ValueList .Builder builder =
3053
3067
com .google .spanner .executor .v1 .ValueList .newBuilder ();
3054
- List <BigDecimal > values = result .getBigDecimalList (i );
3068
+ List <BigDecimal > values = struct .getBigDecimalList (i );
3055
3069
for (BigDecimal bigDec : values ) {
3056
3070
com .google .spanner .executor .v1 .Value .Builder valueProto =
3057
3071
com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3070,7 +3084,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
3070
3084
{
3071
3085
com .google .spanner .executor .v1 .ValueList .Builder builder =
3072
3086
com .google .spanner .executor .v1 .ValueList .newBuilder ();
3073
- List <String > values = result .getJsonList (i );
3087
+ List <String > values = struct .getJsonList (i );
3074
3088
for (String stringValue : values ) {
3075
3089
com .google .spanner .executor .v1 .Value .Builder valueProto =
3076
3090
com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3085,28 +3099,46 @@ private com.google.spanner.executor.v1.ValueList buildRow(
3085
3099
com .google .spanner .v1 .Type .newBuilder ().setCode (TypeCode .JSON ).build ());
3086
3100
}
3087
3101
break ;
3102
+ case STRUCT :
3103
+ {
3104
+ com .google .spanner .executor .v1 .ValueList .Builder builder =
3105
+ com .google .spanner .executor .v1 .ValueList .newBuilder ();
3106
+ List <Struct > values = struct .getStructList (i );
3107
+ for (StructReader structValue : values ) {
3108
+ com .google .spanner .executor .v1 .Value .Builder valueProto =
3109
+ com .google .spanner .executor .v1 .Value .newBuilder ();
3110
+ if (structValue == null ) {
3111
+ builder .addValue (valueProto .setIsNull (true ).build ());
3112
+ } else {
3113
+ builder .addValue (valueProto .setStructValue (buildStruct (structValue ))).build ();
3114
+ }
3115
+ }
3116
+ value .setArrayValue (builder .build ());
3117
+ value .setArrayType (
3118
+ com .google .spanner .v1 .Type .newBuilder ().setCode (TypeCode .JSON ).build ());
3119
+ }
3120
+ break ;
3088
3121
default :
3089
3122
throw SpannerExceptionFactory .newSpannerException (
3090
3123
ErrorCode .INVALID_ARGUMENT ,
3091
3124
"Unsupported row array type: "
3092
- + result .getColumnType (i )
3125
+ + struct .getColumnType (i )
3093
3126
+ " for result type "
3094
- + result .getType ().toString ());
3127
+ + struct .getType ().toString ());
3095
3128
}
3096
3129
break ;
3097
3130
default :
3098
3131
throw SpannerExceptionFactory .newSpannerException (
3099
3132
ErrorCode .INVALID_ARGUMENT ,
3100
3133
"Unsupported row type: "
3101
- + result .getColumnType (i )
3134
+ + struct .getColumnType (i )
3102
3135
+ " for result type "
3103
- + result .getType ().toString ());
3136
+ + struct .getType ().toString ());
3104
3137
}
3105
3138
}
3106
- rowBuilder .addValue (value .build ());
3107
- }
3108
- sender .setRowType (rowTypeBuilder .build ());
3109
- return rowBuilder .build ();
3139
+ structBuilder .addValue (value .build ());
3140
+ };
3141
+ return structBuilder .build ();
3110
3142
}
3111
3143
3112
3144
/** Convert a ListValue proto to a list of cloud Value. */
0 commit comments