@@ -2840,61 +2840,75 @@ private Status processResults(
28402840 /** Convert a result row to a row proto(value list) for sending back to the client. */
28412841 private com .google .spanner .executor .v1 .ValueList buildRow (
28422842 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 ) {
28452849 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 );
28492853 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 );
28542868 com .google .spanner .executor .v1 .Value .Builder value =
28552869 com .google .spanner .executor .v1 .Value .newBuilder ();
2856- if (result .isNull (i )) {
2870+ if (struct .isNull (i )) {
28572871 value .setIsNull (true );
28582872 } else {
28592873 switch (columnType .getCode ()) {
28602874 case BOOL :
2861- value .setBoolValue (result .getBoolean (i ));
2875+ value .setBoolValue (struct .getBoolean (i ));
28622876 break ;
28632877 case FLOAT32 :
2864- value .setDoubleValue ((double ) result .getFloat (i ));
2878+ value .setDoubleValue ((double ) struct .getFloat (i ));
28652879 break ;
28662880 case FLOAT64 :
2867- value .setDoubleValue (result .getDouble (i ));
2881+ value .setDoubleValue (struct .getDouble (i ));
28682882 break ;
28692883 case INT64 :
2870- value .setIntValue (result .getLong (i ));
2884+ value .setIntValue (struct .getLong (i ));
28712885 break ;
28722886 case STRING :
2873- value .setStringValue (result .getString (i ));
2887+ value .setStringValue (struct .getString (i ));
28742888 break ;
28752889 case BYTES :
2876- value .setBytesValue (toByteString (result .getBytes (i )));
2890+ value .setBytesValue (toByteString (struct .getBytes (i )));
28772891 break ;
28782892 case TIMESTAMP :
2879- value .setTimestampValue (timestampToProto (result .getTimestamp (i )));
2893+ value .setTimestampValue (timestampToProto (struct .getTimestamp (i )));
28802894 break ;
28812895 case DATE :
2882- value .setDateDaysValue (daysFromDate (result .getDate (i )));
2896+ value .setDateDaysValue (daysFromDate (struct .getDate (i )));
28832897 break ;
28842898 case NUMERIC :
2885- String ascii = result .getBigDecimal (i ).toPlainString ();
2899+ String ascii = struct .getBigDecimal (i ).toPlainString ();
28862900 value .setStringValue (ascii );
28872901 break ;
28882902 case JSON :
2889- value .setStringValue (result .getJson (i ));
2903+ value .setStringValue (struct .getJson (i ));
28902904 break ;
28912905 case ARRAY :
2892- switch (result .getColumnType (i ).getArrayElementType ().getCode ()) {
2906+ switch (struct .getColumnType (i ).getArrayElementType ().getCode ()) {
28932907 case BOOL :
28942908 {
28952909 com .google .spanner .executor .v1 .ValueList .Builder builder =
28962910 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2897- List <Boolean > values = result .getBooleanList (i );
2911+ List <Boolean > values = struct .getBooleanList (i );
28982912 for (Boolean booleanValue : values ) {
28992913 com .google .spanner .executor .v1 .Value .Builder valueProto =
29002914 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2913,7 +2927,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
29132927 {
29142928 com .google .spanner .executor .v1 .ValueList .Builder builder =
29152929 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2916- List <Float > values = result .getFloatList (i );
2930+ List <Float > values = struct .getFloatList (i );
29172931 for (Float floatValue : values ) {
29182932 com .google .spanner .executor .v1 .Value .Builder valueProto =
29192933 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2932,7 +2946,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
29322946 {
29332947 com .google .spanner .executor .v1 .ValueList .Builder builder =
29342948 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2935- List <Double > values = result .getDoubleList (i );
2949+ List <Double > values = struct .getDoubleList (i );
29362950 for (Double doubleValue : values ) {
29372951 com .google .spanner .executor .v1 .Value .Builder valueProto =
29382952 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2951,7 +2965,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
29512965 {
29522966 com .google .spanner .executor .v1 .ValueList .Builder builder =
29532967 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2954- List <Long > values = result .getLongList (i );
2968+ List <Long > values = struct .getLongList (i );
29552969 for (Long longValue : values ) {
29562970 com .google .spanner .executor .v1 .Value .Builder valueProto =
29572971 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2970,7 +2984,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
29702984 {
29712985 com .google .spanner .executor .v1 .ValueList .Builder builder =
29722986 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2973- List <String > values = result .getStringList (i );
2987+ List <String > values = struct .getStringList (i );
29742988 for (String stringValue : values ) {
29752989 com .google .spanner .executor .v1 .Value .Builder valueProto =
29762990 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -2989,7 +3003,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
29893003 {
29903004 com .google .spanner .executor .v1 .ValueList .Builder builder =
29913005 com .google .spanner .executor .v1 .ValueList .newBuilder ();
2992- List <ByteArray > values = result .getBytesList (i );
3006+ List <ByteArray > values = struct .getBytesList (i );
29933007 for (ByteArray byteArrayValue : values ) {
29943008 com .google .spanner .executor .v1 .Value .Builder valueProto =
29953009 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3011,7 +3025,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
30113025 {
30123026 com .google .spanner .executor .v1 .ValueList .Builder builder =
30133027 com .google .spanner .executor .v1 .ValueList .newBuilder ();
3014- List <Date > values = result .getDateList (i );
3028+ List <Date > values = struct .getDateList (i );
30153029 for (Date dateValue : values ) {
30163030 com .google .spanner .executor .v1 .Value .Builder valueProto =
30173031 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3031,7 +3045,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
30313045 {
30323046 com .google .spanner .executor .v1 .ValueList .Builder builder =
30333047 com .google .spanner .executor .v1 .ValueList .newBuilder ();
3034- List <Timestamp > values = result .getTimestampList (i );
3048+ List <Timestamp > values = struct .getTimestampList (i );
30353049 for (Timestamp timestampValue : values ) {
30363050 com .google .spanner .executor .v1 .Value .Builder valueProto =
30373051 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3051,7 +3065,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
30513065 {
30523066 com .google .spanner .executor .v1 .ValueList .Builder builder =
30533067 com .google .spanner .executor .v1 .ValueList .newBuilder ();
3054- List <BigDecimal > values = result .getBigDecimalList (i );
3068+ List <BigDecimal > values = struct .getBigDecimalList (i );
30553069 for (BigDecimal bigDec : values ) {
30563070 com .google .spanner .executor .v1 .Value .Builder valueProto =
30573071 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3070,7 +3084,7 @@ private com.google.spanner.executor.v1.ValueList buildRow(
30703084 {
30713085 com .google .spanner .executor .v1 .ValueList .Builder builder =
30723086 com .google .spanner .executor .v1 .ValueList .newBuilder ();
3073- List <String > values = result .getJsonList (i );
3087+ List <String > values = struct .getJsonList (i );
30743088 for (String stringValue : values ) {
30753089 com .google .spanner .executor .v1 .Value .Builder valueProto =
30763090 com .google .spanner .executor .v1 .Value .newBuilder ();
@@ -3085,28 +3099,46 @@ private com.google.spanner.executor.v1.ValueList buildRow(
30853099 com .google .spanner .v1 .Type .newBuilder ().setCode (TypeCode .JSON ).build ());
30863100 }
30873101 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 ;
30883121 default :
30893122 throw SpannerExceptionFactory .newSpannerException (
30903123 ErrorCode .INVALID_ARGUMENT ,
30913124 "Unsupported row array type: "
3092- + result .getColumnType (i )
3125+ + struct .getColumnType (i )
30933126 + " for result type "
3094- + result .getType ().toString ());
3127+ + struct .getType ().toString ());
30953128 }
30963129 break ;
30973130 default :
30983131 throw SpannerExceptionFactory .newSpannerException (
30993132 ErrorCode .INVALID_ARGUMENT ,
31003133 "Unsupported row type: "
3101- + result .getColumnType (i )
3134+ + struct .getColumnType (i )
31023135 + " for result type "
3103- + result .getType ().toString ());
3136+ + struct .getType ().toString ());
31043137 }
31053138 }
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 ();
31103142 }
31113143
31123144 /** Convert a ListValue proto to a list of cloud Value. */
0 commit comments