Skip to content

Commit 1dc5a3e

Browse files
feat: Support getOrNull and getOrDefault in Struct (#3914)
* feat: Support getOrNull and getOrDefault in Struct * Addressed comments * Change Function interface to BiFunction * Update clirr ignored differences
1 parent a97728b commit 1dc5a3e

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed

google-cloud-spanner/clirr-ignored-differences.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,4 +1008,24 @@
10081008
<className>com/google/cloud/spanner/TransactionManager</className>
10091009
<method>com.google.cloud.spanner.TransactionContext begin(com.google.cloud.spanner.AbortedException)</method>
10101010
</difference>
1011+
<difference>
1012+
<differenceType>7012</differenceType>
1013+
<className>com/google/cloud/spanner/StructReader</className>
1014+
<method>java.lang.Object getOrNull(int, java.util.function.BiFunction)</method>
1015+
</difference>
1016+
<difference>
1017+
<differenceType>7012</differenceType>
1018+
<className>com/google/cloud/spanner/StructReader</className>
1019+
<method>java.lang.Object getOrNull(java.lang.String, java.util.function.BiFunction)</method>
1020+
</difference>
1021+
<difference>
1022+
<differenceType>7012</differenceType>
1023+
<className>com/google/cloud/spanner/StructReader</className>
1024+
<method>java.lang.Object getOrDefault(int, java.util.function.BiFunction, java.lang.Object)</method>
1025+
</difference>
1026+
<difference>
1027+
<differenceType>7012</differenceType>
1028+
<className>com/google/cloud/spanner/StructReader</className>
1029+
<method>java.lang.Object getOrDefault(java.lang.String, java.util.function.BiFunction, java.lang.Object)</method>
1030+
</difference>
10111031
</differences>

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.math.BigDecimal;
2525
import java.util.List;
2626
import java.util.UUID;
27+
import java.util.function.BiFunction;
2728
import java.util.function.Function;
2829

2930
/**
@@ -176,6 +177,60 @@ default float getFloat(String columnName) {
176177
*/
177178
String getString(String columnName);
178179

180+
/**
181+
* @param columnIndex index of the column
182+
* @return the value of a column with type T or null if the column contains a null value
183+
* <p>Example
184+
* <pre>{@code
185+
* Struct row = ...
186+
* String name = row.getOrNull(1, StructReader::getString)
187+
* }</pre>
188+
*/
189+
default <T> T getOrNull(int columnIndex, BiFunction<StructReader, Integer, T> function) {
190+
return isNull(columnIndex) ? null : function.apply(this, columnIndex);
191+
}
192+
193+
/**
194+
* @param columnName index of the column
195+
* @return the value of a column with type T or null if the column contains a null value
196+
* <p>Example
197+
* <pre>{@code
198+
* Struct row = ...
199+
* String name = row.getOrNull("name", StructReader::getString)
200+
* }</pre>
201+
*/
202+
default <T> T getOrNull(String columnName, BiFunction<StructReader, String, T> function) {
203+
return isNull(columnName) ? null : function.apply(this, columnName);
204+
}
205+
206+
/**
207+
* @param columnIndex index of the column
208+
* @return the value of a column with type T, or the given default if the column value is null
209+
* <p>Example
210+
* <pre>{@code
211+
* Struct row = ...
212+
* String name = row.getOrDefault(1, StructReader::getString, "")
213+
* }</pre>
214+
*/
215+
default <T> T getOrDefault(
216+
int columnIndex, BiFunction<StructReader, Integer, T> function, T defaultValue) {
217+
return isNull(columnIndex) ? defaultValue : function.apply(this, columnIndex);
218+
}
219+
220+
/**
221+
* @param columnName name of the column
222+
* @return the value of a column with type T, or the given default if the column value is null
223+
* <p>Example
224+
* <pre>{@code
225+
* Struct row = ...
226+
* String name = row.getOrDefault("name", StructReader::getString, "")
227+
* }</pre>
228+
*/
229+
default <T> T getOrDefault(
230+
String columnName, BiFunction<StructReader, String, T> function, T defaultValue) {
231+
return isNull(columnName) ? defaultValue : function.apply(this, columnName);
232+
}
233+
179234
/**
180235
* @param columnIndex index of the column
181236
* @return the value of a non-{@code NULL} column with type {@link Type#json()}.

google-cloud-spanner/src/test/java/com/google/cloud/spanner/StructTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,48 @@ public void builder() {
5757
assertThat(struct.getLong(1)).isEqualTo(2);
5858
}
5959

60+
@Test
61+
public void getOrNullTests() {
62+
Struct struct =
63+
Struct.newBuilder()
64+
.set("f1")
65+
.to("x")
66+
.set("f2")
67+
.to(2)
68+
.set("f3")
69+
.to(Value.bool(null))
70+
.build();
71+
String column1 = struct.getOrNull(0, StructReader::getString);
72+
assertThat(column1).isEqualTo("x");
73+
74+
Long column2 = struct.getOrNull(1, StructReader::getLong);
75+
assertThat(column2).isEqualTo(2);
76+
77+
String column3 = struct.getOrNull("f3", StructReader::getString);
78+
assertThat(column3).isNull();
79+
}
80+
81+
@Test
82+
public void getOrDefaultTests() {
83+
Struct struct =
84+
Struct.newBuilder()
85+
.set("f1")
86+
.to("x")
87+
.set("f2")
88+
.to(2)
89+
.set("f3")
90+
.to(Value.bool(null))
91+
.build();
92+
String column1 = struct.getOrDefault(0, StructReader::getString, "");
93+
assertThat(column1).isEqualTo("x");
94+
95+
Long column2 = struct.getOrDefault("f2", StructReader::getLong, -1L);
96+
assertThat(column2).isEqualTo(2);
97+
98+
String column3 = struct.getOrDefault(2, StructReader::getString, "");
99+
assertThat(column3).isEqualTo("");
100+
}
101+
60102
@Test
61103
public void duplicateFields() {
62104
// Duplicate fields are allowed - some SQL queries produce this type of value.

0 commit comments

Comments
 (0)