@@ -2842,61 +2842,75 @@ private Status processResults(
28422842 /** Convert a result row to a row proto(value list) for sending back to the client. */
28432843 private com .google .spanner .executor .v1 .ValueList buildRow (
28442844 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 ) {
28472851 com .google .spanner .v1 .StructType .Builder rowTypeBuilder =
2848- 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 );
2852+ com .google .spanner .v1 .StructType .newBuilder ();
2853+ for (int i = 0 ; i < struct .getColumnCount (); ++i ) {
2854+ com .google .cloud .spanner .Type columnType = struct .getColumnType (i );
28512855 rowTypeBuilder .addFields (
2852- com .google .spanner .v1 .StructType .Field .newBuilder ()
2853- .setName (result .getType ().getStructFields ().get (i ).getName ())
2854- .setType (cloudTypeToTypeProto (columnType ))
2855- .build ());
2856+ com .google .spanner .v1 .StructType .Field .newBuilder ()
2857+ .setName (struct .getType ().getStructFields ().get (i ).getName ())
2858+ .setType (cloudTypeToTypeProto (columnType ))
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 );
28562870 com .google .spanner .executor .v1 .Value .Builder value =
28572871 com .google .spanner .executor .v1 .Value .newBuilder ();
2858- if (result .isNull (i )) {
2872+ if (struct .isNull (i )) {
28592873 value .setIsNull (true );
28602874 } else {
28612875 switch (columnType .getCode ()) {
28622876 case BOOL :
2863- value .setBoolValue (result .getBoolean (i ));
2877+ value .setBoolValue (struct .getBoolean (i ));
28642878 break ;
28652879 case FLOAT32 :
2866- value .setDoubleValue ((double ) result .getFloat (i ));
2880+ value .setDoubleValue ((double ) struct .getFloat (i ));
28672881 break ;
28682882 case FLOAT64 :
2869- value .setDoubleValue (result .getDouble (i ));
2883+ value .setDoubleValue (struct .getDouble (i ));
28702884 break ;
28712885 case INT64 :
2872- value .setIntValue (result .getLong (i ));
2886+ value .setIntValue (struct .getLong (i ));
28732887 break ;
28742888 case STRING :
2875- value .setStringValue (result .getString (i ));
2889+ value .setStringValue (struct .getString (i ));
28762890 break ;
28772891 case BYTES :
2878- value .setBytesValue (toByteString (result .getBytes (i )));
2892+ value .setBytesValue (toByteString (struct .getBytes (i )));
28792893 break ;
28802894 case TIMESTAMP :
2881- value .setTimestampValue (timestampToProto (result .getTimestamp (i )));
2895+ value .setTimestampValue (timestampToProto (struct .getTimestamp (i )));
28822896 break ;
28832897 case DATE :
2884- value .setDateDaysValue (daysFromDate (result .getDate (i )));
2898+ value .setDateDaysValue (daysFromDate (struct .getDate (i )));
28852899 break ;
28862900 case NUMERIC :
2887- String ascii = result .getBigDecimal (i ).toPlainString ();
2901+ String ascii = struct .getBigDecimal (i ).toPlainString ();
28882902 value .setStringValue (ascii );
28892903 break ;
28902904 case JSON :
2891- value .setStringValue (result .getJson (i ));
2905+ value .setStringValue (struct .getJson (i ));
28922906 break ;
28932907 case ARRAY :
2894- switch (result .getColumnType (i ).getArrayElementType ().getCode ()) {
2908+ switch (struct .getColumnType (i ).getArrayElementType ().getCode ()) {
28952909 case BOOL :
28962910 {
28972911 com .google .spanner .executor .v1 .ValueList .Builder builder =
28982912 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2899- List <Boolean > values = result .getBooleanList (i );
2913+ List <Boolean > values = struct .getBooleanList (i );
29002914 for (Boolean booleanValue : values ) {
29012915 com .google .spanner .executor .v1 .Value .Builder valueProto =
29022916 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2915,7 +2929,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
29152929 {
29162930 com .google .spanner .executor .v1 .ValueList .Builder builder =
29172931 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2918- List <Float > values = result .getFloatList (i );
2932+ List <Float > values = struct .getFloatList (i );
29192933 for (Float floatValue : values ) {
29202934 com .google .spanner .executor .v1 .Value .Builder valueProto =
29212935 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2934,7 +2948,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
29342948 {
29352949 com .google .spanner .executor .v1 .ValueList .Builder builder =
29362950 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2937- List <Double > values = result .getDoubleList (i );
2951+ List <Double > values = struct .getDoubleList (i );
29382952 for (Double doubleValue : values ) {
29392953 com .google .spanner .executor .v1 .Value .Builder valueProto =
29402954 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2953,7 +2967,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
29532967 {
29542968 com .google .spanner .executor .v1 .ValueList .Builder builder =
29552969 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2956- List <Long > values = result .getLongList (i );
2970+ List <Long > values = struct .getLongList (i );
29572971 for (Long longValue : values ) {
29582972 com .google .spanner .executor .v1 .Value .Builder valueProto =
29592973 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2972,7 +2986,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
29722986 {
29732987 com .google .spanner .executor .v1 .ValueList .Builder builder =
29742988 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2975- List <String > values = result .getStringList (i );
2989+ List <String > values = struct .getStringList (i );
29762990 for (String stringValue : values ) {
29772991 com .google .spanner .executor .v1 .Value .Builder valueProto =
29782992 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2991,7 +3005,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
29913005 {
29923006 com .google .spanner .executor .v1 .ValueList .Builder builder =
29933007 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2994- List <ByteArray > values = result .getBytesList (i );
3008+ List <ByteArray > values = struct .getBytesList (i );
29953009 for (ByteArray byteArrayValue : values ) {
29963010 com .google .spanner .executor .v1 .Value .Builder valueProto =
29973011 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3013,7 +3027,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
30133027 {
30143028 com .google .spanner .executor .v1 .ValueList .Builder builder =
30153029 com .google .spanner .executor .v1 .ValueList .newBuilder ();
3016- List <Date > values = result .getDateList (i );
3030+ List <Date > values = struct .getDateList (i );
30173031 for (Date dateValue : values ) {
30183032 com .google .spanner .executor .v1 .Value .Builder valueProto =
30193033 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3033,7 +3047,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
30333047 {
30343048 com .google .spanner .executor .v1 .ValueList .Builder builder =
30353049 com .google .spanner .executor .v1 .ValueList .newBuilder ();
3036- List <Timestamp > values = result .getTimestampList (i );
3050+ List <Timestamp > values = struct .getTimestampList (i );
30373051 for (Timestamp timestampValue : values ) {
30383052 com .google .spanner .executor .v1 .Value .Builder valueProto =
30393053 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3053,7 +3067,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
30533067 {
30543068 com .google .spanner .executor .v1 .ValueList .Builder builder =
30553069 com .google .spanner .executor .v1 .ValueList .newBuilder ();
3056- List <BigDecimal > values = result .getBigDecimalList (i );
3070+ List <BigDecimal > values = struct .getBigDecimalList (i );
30573071 for (BigDecimal bigDec : values ) {
30583072 com .google .spanner .executor .v1 .Value .Builder valueProto =
30593073 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3072,7 +3086,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
30723086 {
30733087 com .google .spanner .executor .v1 .ValueList .Builder builder =
30743088 com .google .spanner .executor .v1 .ValueList .newBuilder ();
3075- List <String > values = result .getJsonList (i );
3089+ List <String > values = struct .getJsonList (i );
30763090 for (String stringValue : values ) {
30773091 com .google .spanner .executor .v1 .Value .Builder valueProto =
30783092 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3087,28 +3101,46 @@ private com.google.spanner.executor.v1.ValueList buildRow(
30873101 com .google .spanner .v1 .Type .newBuilder ().setCode (TypeCode .JSON ).build ());
30883102 }
30893103 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 .JSON ).build ());
3121+ }
3122+ break ;
30903123 default :
30913124 throw SpannerExceptionFactory .newSpannerException (
30923125 ErrorCode .INVALID_ARGUMENT ,
30933126 "Unsupported row array type: "
3094- + result .getColumnType (i )
3127+ + struct .getColumnType (i )
30953128 + " for result type "
3096- + result .getType ().toString ());
3129+ + struct .getType ().toString ());
30973130 }
30983131 break ;
30993132 default :
31003133 throw SpannerExceptionFactory .newSpannerException (
31013134 ErrorCode .INVALID_ARGUMENT ,
31023135 "Unsupported row type: "
3103- + result .getColumnType (i )
3136+ + struct .getColumnType (i )
31043137 + " for result type "
3105- + result .getType ().toString ());
3138+ + struct .getType ().toString ());
31063139 }
31073140 }
3108- rowBuilder .addValue (value .build ());
3109- }
3110- sender .setRowType (rowTypeBuilder .build ());
3111- return rowBuilder .build ();
3141+ structBuilder .addValue (value .build ());
3142+ };
3143+ return structBuilder .build ();
31123144 }
31133145
31143146 /** Convert a ListValue proto to a list of cloud Value. */
0 commit comments