diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml index 94bb5870f81..46a11518dbb 100644 --- a/google-cloud-spanner/clirr-ignored-differences.xml +++ b/google-cloud-spanner/clirr-ignored-differences.xml @@ -1008,4 +1008,24 @@ com/google/cloud/spanner/TransactionManager com.google.cloud.spanner.TransactionContext begin(com.google.cloud.spanner.AbortedException) + + 7012 + com/google/cloud/spanner/StructReader + java.lang.Object getOrNull(int, java.util.function.BiFunction) + + + 7012 + com/google/cloud/spanner/StructReader + java.lang.Object getOrNull(java.lang.String, java.util.function.BiFunction) + + + 7012 + com/google/cloud/spanner/StructReader + java.lang.Object getOrDefault(int, java.util.function.BiFunction, java.lang.Object) + + + 7012 + com/google/cloud/spanner/StructReader + java.lang.Object getOrDefault(java.lang.String, java.util.function.BiFunction, java.lang.Object) + diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/StructReader.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/StructReader.java index f690011f389..ab645588bf1 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/StructReader.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/StructReader.java @@ -24,6 +24,7 @@ import java.math.BigDecimal; import java.util.List; import java.util.UUID; +import java.util.function.BiFunction; import java.util.function.Function; /** @@ -176,6 +177,60 @@ default float getFloat(String columnName) { */ String getString(String columnName); + /** + * @param columnIndex index of the column + * @return the value of a column with type T or null if the column contains a null value + *

Example + *

{@code
+   * Struct row = ...
+   * String name = row.getOrNull(1, StructReader::getString)
+   * }
+ */ + default T getOrNull(int columnIndex, BiFunction function) { + return isNull(columnIndex) ? null : function.apply(this, columnIndex); + } + + /** + * @param columnName index of the column + * @return the value of a column with type T or null if the column contains a null value + *

Example + *

{@code
+   * Struct row = ...
+   * String name = row.getOrNull("name", StructReader::getString)
+   * }
+ */ + default T getOrNull(String columnName, BiFunction function) { + return isNull(columnName) ? null : function.apply(this, columnName); + } + + /** + * @param columnIndex index of the column + * @return the value of a column with type T, or the given default if the column value is null + *

Example + *

{@code
+   * Struct row = ...
+   * String name = row.getOrDefault(1, StructReader::getString, "")
+   * }
+ */ + default T getOrDefault( + int columnIndex, BiFunction function, T defaultValue) { + return isNull(columnIndex) ? defaultValue : function.apply(this, columnIndex); + } + + /** + * @param columnName name of the column + * @return the value of a column with type T, or the given default if the column value is null + *

Example + *

{@code
+   * Struct row = ...
+   * String name = row.getOrDefault("name", StructReader::getString, "")
+   * }
+ */ + default T getOrDefault( + String columnName, BiFunction function, T defaultValue) { + return isNull(columnName) ? defaultValue : function.apply(this, columnName); + } + /** * @param columnIndex index of the column * @return the value of a non-{@code NULL} column with type {@link Type#json()}. diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StructTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StructTest.java index d357a14f9d0..55d066e165e 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StructTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StructTest.java @@ -57,6 +57,48 @@ public void builder() { assertThat(struct.getLong(1)).isEqualTo(2); } + @Test + public void getOrNullTests() { + Struct struct = + Struct.newBuilder() + .set("f1") + .to("x") + .set("f2") + .to(2) + .set("f3") + .to(Value.bool(null)) + .build(); + String column1 = struct.getOrNull(0, StructReader::getString); + assertThat(column1).isEqualTo("x"); + + Long column2 = struct.getOrNull(1, StructReader::getLong); + assertThat(column2).isEqualTo(2); + + String column3 = struct.getOrNull("f3", StructReader::getString); + assertThat(column3).isNull(); + } + + @Test + public void getOrDefaultTests() { + Struct struct = + Struct.newBuilder() + .set("f1") + .to("x") + .set("f2") + .to(2) + .set("f3") + .to(Value.bool(null)) + .build(); + String column1 = struct.getOrDefault(0, StructReader::getString, ""); + assertThat(column1).isEqualTo("x"); + + Long column2 = struct.getOrDefault("f2", StructReader::getLong, -1L); + assertThat(column2).isEqualTo(2); + + String column3 = struct.getOrDefault(2, StructReader::getString, ""); + assertThat(column3).isEqualTo(""); + } + @Test public void duplicateFields() { // Duplicate fields are allowed - some SQL queries produce this type of value.