Skip to content

Commit f853918

Browse files
refactor: Removing duplicated code to handle array values (#2143)
* refactor: Removing duplicated code to handle array values The same deserialization logic for data types have been duplicated at multiple places which is prone to error. * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * refactor: Using lazy computation for all the data types and adding docs Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 4d74a0d commit f853918

File tree

2 files changed

+93
-90
lines changed

2 files changed

+93
-90
lines changed

google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java

Lines changed: 3 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
import java.util.concurrent.TimeUnit;
6868
import java.util.logging.Level;
6969
import java.util.logging.Logger;
70-
import java.util.stream.Collectors;
7170
import javax.annotation.Nullable;
7271

7372
/** Implementation of {@link ResultSet}. */
@@ -547,88 +546,24 @@ private static Struct decodeStructValue(Type structType, ListValue structValue)
547546

548547
static Object decodeArrayValue(Type elementType, ListValue listValue) {
549548
switch (elementType.getCode()) {
550-
case BOOL:
551-
// Use a view: element conversion is virtually free.
552-
return Lists.transform(
553-
listValue.getValuesList(),
554-
input -> input.getKindCase() == KindCase.NULL_VALUE ? null : input.getBoolValue());
555549
case INT64:
556550
// For int64/float64 types, use custom containers. These avoid wrapper object
557551
// creation for non-null arrays.
558552
return new Int64Array(listValue);
559553
case FLOAT64:
560554
return new Float64Array(listValue);
555+
case BOOL:
561556
case NUMERIC:
562-
{
563-
// Materialize list: element conversion is expensive and should happen only once.
564-
ArrayList<Object> list = new ArrayList<>(listValue.getValuesCount());
565-
for (com.google.protobuf.Value value : listValue.getValuesList()) {
566-
list.add(
567-
value.getKindCase() == KindCase.NULL_VALUE
568-
? null
569-
: new BigDecimal(value.getStringValue()));
570-
}
571-
return list;
572-
}
573557
case PG_NUMERIC:
574558
case STRING:
575559
case JSON:
576560
case PG_JSONB:
577-
return listValue.getValuesList().stream()
578-
.map(
579-
input ->
580-
input.getKindCase() == KindCase.NULL_VALUE ? null : input.getStringValue())
581-
.collect(Collectors.toList());
582561
case BYTES:
583-
{
584-
// Materialize list: element conversion is expensive and should happen only once.
585-
ArrayList<Object> list = new ArrayList<>(listValue.getValuesCount());
586-
for (com.google.protobuf.Value value : listValue.getValuesList()) {
587-
list.add(
588-
value.getKindCase() == KindCase.NULL_VALUE
589-
? null
590-
: ByteArray.fromBase64(value.getStringValue()));
591-
}
592-
return list;
593-
}
594562
case TIMESTAMP:
595-
{
596-
// Materialize list: element conversion is expensive and should happen only once.
597-
ArrayList<Object> list = new ArrayList<>(listValue.getValuesCount());
598-
for (com.google.protobuf.Value value : listValue.getValuesList()) {
599-
list.add(
600-
value.getKindCase() == KindCase.NULL_VALUE
601-
? null
602-
: Timestamp.parseTimestamp(value.getStringValue()));
603-
}
604-
return list;
605-
}
606563
case DATE:
607-
{
608-
// Materialize list: element conversion is expensive and should happen only once.
609-
ArrayList<Object> list = new ArrayList<>(listValue.getValuesCount());
610-
for (com.google.protobuf.Value value : listValue.getValuesList()) {
611-
list.add(
612-
value.getKindCase() == KindCase.NULL_VALUE
613-
? null
614-
: Date.parseDate(value.getStringValue()));
615-
}
616-
return list;
617-
}
618-
619564
case STRUCT:
620-
{
621-
ArrayList<Struct> list = new ArrayList<>(listValue.getValuesCount());
622-
for (com.google.protobuf.Value value : listValue.getValuesList()) {
623-
if (value.getKindCase() == KindCase.NULL_VALUE) {
624-
list.add(null);
625-
} else {
626-
ListValue structValue = value.getListValue();
627-
list.add(decodeStructValue(elementType, structValue));
628-
}
629-
}
630-
return list;
631-
}
565+
return Lists.transform(
566+
listValue.getValuesList(), input -> decodeValue(elementType, input));
632567
default:
633568
throw new AssertionError("Unhandled type code: " + elementType.getCode());
634569
}

google-cloud-spanner/src/main/java/com/google/cloud/spanner/StructReader.java

Lines changed: 90 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,18 @@ default Value getValue(String columnName) {
178178
*/
179179
boolean[] getBooleanArray(String columnName);
180180

181-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bool())}. */
181+
/**
182+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bool())}. The
183+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
184+
* each element in the list multiple times.
185+
*/
182186
List<Boolean> getBooleanList(int columnIndex);
183187

184-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bool())}. */
188+
/**
189+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bool())}. The
190+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
191+
* each element in the list multiple times.
192+
*/
185193
List<Boolean> getBooleanList(String columnName);
186194

187195
/**
@@ -200,10 +208,18 @@ default Value getValue(String columnName) {
200208
*/
201209
long[] getLongArray(String columnName);
202210

203-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.int64())}. */
211+
/**
212+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.int64())}. The
213+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
214+
* each element in the list multiple times.
215+
*/
204216
List<Long> getLongList(int columnIndex);
205217

206-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.int64())}. */
218+
/**
219+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.int64())}. The
220+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
221+
* each element in the list multiple times.
222+
*/
207223
List<Long> getLongList(String columnName);
208224

209225
/**
@@ -223,84 +239,136 @@ default Value getValue(String columnName) {
223239
double[] getDoubleArray(String columnName);
224240

225241
/**
226-
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.float64())}.
242+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.float64())} The
243+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
244+
* each element in the list multiple times.
227245
*/
228246
List<Double> getDoubleList(int columnIndex);
229247

230248
/**
231-
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.float64())}.
249+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.float64())} The
250+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
251+
* each element in the list multiple times.
232252
*/
233253
List<Double> getDoubleList(String columnName);
234254

235255
/**
236-
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.numeric())}.
256+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.numeric())} The
257+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
258+
* each element in the list multiple times.
237259
*/
238260
List<BigDecimal> getBigDecimalList(int columnIndex);
239261

240262
/**
241-
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.numeric())}.
263+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.numeric())} The
264+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
265+
* each element in the list multiple times.
242266
*/
243267
List<BigDecimal> getBigDecimalList(String columnName);
244268

245-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. */
269+
/**
270+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. The
271+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
272+
* each element in the list multiple times.
273+
*/
246274
List<String> getStringList(int columnIndex);
247275

248-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. */
276+
/**
277+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.string())}. The
278+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
279+
* each element in the list multiple times.
280+
*/
249281
List<String> getStringList(String columnName);
250282

251-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.json())}. */
283+
/**
284+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.json())}. The
285+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
286+
* each element in the list multiple times.
287+
*/
252288
default List<String> getJsonList(int columnIndex) {
253289
throw new UnsupportedOperationException("method should be overwritten");
254290
};
255291

256-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.json())}. */
292+
/**
293+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.json())}. The
294+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
295+
* each element in the list multiple times.
296+
*/
257297
default List<String> getJsonList(String columnName) {
258298
throw new UnsupportedOperationException("method should be overwritten");
259299
};
260300

261301
/**
262-
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.pgJsonb())}.
302+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.pgJsonb())} The
303+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
304+
* each element in the list multiple times.
263305
*/
264306
default List<String> getPgJsonbList(int columnIndex) {
265307
throw new UnsupportedOperationException("method should be overwritten");
266308
};
267309

268310
/**
269-
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.pgJsonb())}.
311+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.pgJsonb())} The
312+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
313+
* each element in the list multiple times.
270314
*/
271315
default List<String> getPgJsonbList(String columnName) {
272316
throw new UnsupportedOperationException("method should be overwritten");
273317
};
274318

275-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bytes())}. */
319+
/**
320+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bytes())}. The
321+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
322+
* each element in the list multiple times.
323+
*/
276324
List<ByteArray> getBytesList(int columnIndex);
277325

278-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bytes())}. */
326+
/**
327+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.bytes())}. The
328+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
329+
* each element in the list multiple times.
330+
*/
279331
List<ByteArray> getBytesList(String columnName);
280332

281333
/**
282-
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.timestamp())}.
334+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.timestamp())}
335+
* The list returned by this method is lazily constructed. Create a copy of it if you intend to
336+
* access each element in the list multiple times.
283337
*/
284338
List<Timestamp> getTimestampList(int columnIndex);
285339

286340
/**
287-
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.timestamp())}.
341+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.timestamp())}
342+
* The list returned by this method is lazily constructed. Create a copy of it if you intend to
343+
* access each element in the list multiple times.
288344
*/
289345
List<Timestamp> getTimestampList(String columnName);
290346

291-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.date())}. */
347+
/**
348+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.date())}. The
349+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
350+
* each element in the list multiple times.
351+
*/
292352
List<Date> getDateList(int columnIndex);
293353

294-
/** Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.date())}. */
354+
/**
355+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.date())}. The
356+
* list returned by this method is lazily constructed. Create a copy of it if you intend to access
357+
* each element in the list multiple times.
358+
*/
295359
List<Date> getDateList(String columnName);
296360

297361
/**
298-
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.struct(...))}.
362+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.struct(...))}
363+
* The list returned by this method is lazily constructed. Create a copy of it if you intend to
364+
* access each element in the list multiple times.
299365
*/
300366
List<Struct> getStructList(int columnIndex);
301367

302368
/**
303-
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.struct(...))}.
369+
* Returns the value of a non-{@code NULL} column with type {@code Type.array(Type.struct(...))}
370+
* The list returned by this method is lazily constructed. Create a copy of it if you intend to
371+
* access each element in the list multiple times.
304372
*/
305373
List<Struct> getStructList(String columnName);
306374
}

0 commit comments

Comments
 (0)