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