Skip to content

Commit 19b7976

Browse files
arawindgcf-owl-bot[bot]olavloite
authored
feat: support float32 type (#2894)
* feat: float32 changes with unit and integration tests * Update formatting and clirr * Update the hashCode logic to account for NaN equality * Prevent FLOAT32 integration tests from running on emulator and production * Fix integration tests for FLOAT32 * Update float32UntypedParameters test to work with PG dialect too * Split the parameters test in ITQueryTest into supported + currently-unsupported tests. * Split the Mutation.isNaN method to make it more readable * test: added some additional tests * Update to resolve comments on PR#2894. Major change: Ensures that the new methods in interfaces do not break for older clients. Minor changes: remove double cast; remove dependency on Truth assertions; remove unnecessary logic in Mutations::isNaN * Un-ignore the skipped FLOAT32 tests as the backend fixes have been deployed * Un-ignore the float32 tests in ITQueryTest --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com> Co-authored-by: Knut Olav Løite <koloite@gmail.com>
1 parent 4f7d28b commit 19b7976

29 files changed

+1544
-23
lines changed

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

+44-2
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,48 @@
506506
<method>com.google.cloud.spanner.connection.StatementResult execute(com.google.cloud.spanner.Statement, java.util.Set)</method>
507507
</difference>
508508

509+
<!-- FLOAT32 -->
510+
<difference>
511+
<differenceType>7012</differenceType>
512+
<className>com/google/cloud/spanner/StructReader</className>
513+
<method>float getFloat(int)</method>
514+
</difference>
515+
<difference>
516+
<differenceType>7012</differenceType>
517+
<className>com/google/cloud/spanner/StructReader</className>
518+
<method>float getFloat(java.lang.String)</method>
519+
</difference>
520+
<difference>
521+
<differenceType>7012</differenceType>
522+
<className>com/google/cloud/spanner/StructReader</className>
523+
<method>float[] getFloatArray(int)</method>
524+
</difference>
525+
<difference>
526+
<differenceType>7012</differenceType>
527+
<className>com/google/cloud/spanner/StructReader</className>
528+
<method>float[] getFloatArray(java.lang.String)</method>
529+
</difference>
530+
<difference>
531+
<differenceType>7012</differenceType>
532+
<className>com/google/cloud/spanner/StructReader</className>
533+
<method>java.util.List getFloatList(int)</method>
534+
</difference>
535+
<difference>
536+
<differenceType>7012</differenceType>
537+
<className>com/google/cloud/spanner/StructReader</className>
538+
<method>java.util.List getFloatList(java.lang.String)</method>
539+
</difference>
540+
<difference>
541+
<differenceType>7013</differenceType>
542+
<className>com/google/cloud/spanner/Value</className>
543+
<method>float getFloat32()</method>
544+
</difference>
545+
<difference>
546+
<differenceType>7013</differenceType>
547+
<className>com/google/cloud/spanner/Value</className>
548+
<method>java.util.List getFloat32Array()</method>
549+
</difference>
550+
509551
<!-- (Internal change, use stream timeout) -->
510552
<difference>
511553
<differenceType>7012</differenceType>
@@ -569,7 +611,7 @@
569611
<method>void setSpan(io.opencensus.trace.Span)</method>
570612
<to>void setSpan(com.google.cloud.spanner.ISpan)</to>
571613
</difference>
572-
614+
573615
<!-- Added DirectedReadOptions -->
574616
<difference>
575617
<differenceType>7012</differenceType>
@@ -580,5 +622,5 @@
580622
<differenceType>7012</differenceType>
581623
<className>com/google/cloud/spanner/connection/Connection</className>
582624
<method>void setDirectedRead(com.google.spanner.v1.DirectedReadOptions)</method>
583-
</difference>
625+
</difference>
584626
</differences>

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

+72-4
Original file line numberDiff line numberDiff line change
@@ -173,16 +173,44 @@ static double valueProtoToFloat64(com.google.protobuf.Value proto) {
173173
return proto.getNumberValue();
174174
}
175175

176+
static float valueProtoToFloat32(com.google.protobuf.Value proto) {
177+
if (proto.getKindCase() == KindCase.STRING_VALUE) {
178+
switch (proto.getStringValue()) {
179+
case "-Infinity":
180+
return Float.NEGATIVE_INFINITY;
181+
case "Infinity":
182+
return Float.POSITIVE_INFINITY;
183+
case "NaN":
184+
return Float.NaN;
185+
default:
186+
// Fall-through to handling below to produce an error.
187+
}
188+
}
189+
if (proto.getKindCase() != KindCase.NUMBER_VALUE) {
190+
throw newSpannerException(
191+
ErrorCode.INTERNAL,
192+
"Invalid value for column type "
193+
+ Type.float32()
194+
+ " expected NUMBER_VALUE or STRING_VALUE with value one of"
195+
+ " \"Infinity\", \"-Infinity\", or \"NaN\" but was "
196+
+ proto.getKindCase()
197+
+ (proto.getKindCase() == KindCase.STRING_VALUE
198+
? " with value \"" + proto.getStringValue() + "\""
199+
: ""));
200+
}
201+
return (float) proto.getNumberValue();
202+
}
203+
176204
static NullPointerException throwNotNull(int columnIndex) {
177205
throw new NullPointerException(
178206
"Cannot call array getter for column " + columnIndex + " with null elements");
179207
}
180208

181209
/**
182-
* Memory-optimized base class for {@code ARRAY<INT64>} and {@code ARRAY<FLOAT64>} types. Both of
183-
* these involve conversions from the type yielded by JSON parsing, which are {@code String} and
184-
* {@code BigDecimal} respectively. Rather than construct new wrapper objects for each array
185-
* element, we use primitive arrays and a {@code BitSet} to track nulls.
210+
* Memory-optimized base class for {@code ARRAY<INT64>}, {@code ARRAY<FLOAT32>} and {@code
211+
* ARRAY<FLOAT64>} types. All of these involve conversions from the type yielded by JSON parsing,
212+
* which are {@code String} and {@code BigDecimal} respectively. Rather than construct new wrapper
213+
* objects for each array element, we use primitive arrays and a {@code BitSet} to track nulls.
186214
*/
187215
abstract static class PrimitiveArray<T, A> extends AbstractList<T> {
188216
private final A data;
@@ -264,6 +292,31 @@ Long get(long[] array, int i) {
264292
}
265293
}
266294

295+
static class Float32Array extends PrimitiveArray<Float, float[]> {
296+
Float32Array(ListValue protoList) {
297+
super(protoList);
298+
}
299+
300+
Float32Array(float[] data, BitSet nulls) {
301+
super(data, nulls, data.length);
302+
}
303+
304+
@Override
305+
float[] newArray(int size) {
306+
return new float[size];
307+
}
308+
309+
@Override
310+
void setProto(float[] array, int i, com.google.protobuf.Value protoValue) {
311+
array[i] = valueProtoToFloat32(protoValue);
312+
}
313+
314+
@Override
315+
Float get(float[] array, int i) {
316+
return array[i];
317+
}
318+
}
319+
267320
static class Float64Array extends PrimitiveArray<Double, double[]> {
268321
Float64Array(ListValue protoList) {
269322
super(protoList);
@@ -306,6 +359,11 @@ protected long getLongInternal(int columnIndex) {
306359
return currRow().getLongInternal(columnIndex);
307360
}
308361

362+
@Override
363+
protected float getFloatInternal(int columnIndex) {
364+
return currRow().getFloatInternal(columnIndex);
365+
}
366+
309367
@Override
310368
protected double getDoubleInternal(int columnIndex) {
311369
return currRow().getDoubleInternal(columnIndex);
@@ -382,6 +440,16 @@ protected List<Long> getLongListInternal(int columnIndex) {
382440
return currRow().getLongListInternal(columnIndex);
383441
}
384442

443+
@Override
444+
protected float[] getFloatArrayInternal(int columnIndex) {
445+
return currRow().getFloatArrayInternal(columnIndex);
446+
}
447+
448+
@Override
449+
protected List<Float> getFloatListInternal(int columnIndex) {
450+
return currRow().getFloatListInternal(columnIndex);
451+
}
452+
385453
@Override
386454
protected double[] getDoubleArrayInternal(int columnIndex) {
387455
return currRow().getDoubleArrayInternal(columnIndex);

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

+51
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public abstract class AbstractStructReader implements StructReader {
4343

4444
protected abstract long getLongInternal(int columnIndex);
4545

46+
protected float getFloatInternal(int columnIndex) {
47+
throw new UnsupportedOperationException("Not implemented");
48+
}
49+
4650
protected abstract double getDoubleInternal(int columnIndex);
4751

4852
protected abstract BigDecimal getBigDecimalInternal(int columnIndex);
@@ -94,6 +98,14 @@ protected Value getValueInternal(int columnIndex) {
9498

9599
protected abstract List<Long> getLongListInternal(int columnIndex);
96100

101+
protected float[] getFloatArrayInternal(int columnIndex) {
102+
throw new UnsupportedOperationException("Not implemented");
103+
}
104+
105+
protected List<Float> getFloatListInternal(int columnIndex) {
106+
throw new UnsupportedOperationException("Not implemented");
107+
}
108+
97109
protected abstract double[] getDoubleArrayInternal(int columnIndex);
98110

99111
protected abstract List<Double> getDoubleListInternal(int columnIndex);
@@ -164,6 +176,19 @@ public long getLong(String columnName) {
164176
return getLongInternal(columnIndex);
165177
}
166178

179+
@Override
180+
public float getFloat(int columnIndex) {
181+
checkNonNullOfType(columnIndex, Type.float32(), columnIndex);
182+
return getFloatInternal(columnIndex);
183+
}
184+
185+
@Override
186+
public float getFloat(String columnName) {
187+
int columnIndex = getColumnIndex(columnName);
188+
checkNonNullOfType(columnIndex, Type.float32(), columnName);
189+
return getFloatInternal(columnIndex);
190+
}
191+
167192
@Override
168193
public double getDouble(int columnIndex) {
169194
checkNonNullOfType(columnIndex, Type.float64(), columnIndex);
@@ -368,6 +393,32 @@ public List<Long> getLongList(String columnName) {
368393
return getLongListInternal(columnIndex);
369394
}
370395

396+
@Override
397+
public float[] getFloatArray(int columnIndex) {
398+
checkNonNullOfType(columnIndex, Type.array(Type.float32()), columnIndex);
399+
return getFloatArrayInternal(columnIndex);
400+
}
401+
402+
@Override
403+
public float[] getFloatArray(String columnName) {
404+
int columnIndex = getColumnIndex(columnName);
405+
checkNonNullOfType(columnIndex, Type.array(Type.float32()), columnName);
406+
return getFloatArrayInternal(columnIndex);
407+
}
408+
409+
@Override
410+
public List<Float> getFloatList(int columnIndex) {
411+
checkNonNullOfType(columnIndex, Type.array(Type.float32()), columnIndex);
412+
return getFloatListInternal(columnIndex);
413+
}
414+
415+
@Override
416+
public List<Float> getFloatList(String columnName) {
417+
int columnIndex = getColumnIndex(columnName);
418+
checkNonNullOfType(columnIndex, Type.array(Type.float32()), columnName);
419+
return getFloatListInternal(columnIndex);
420+
}
421+
371422
@Override
372423
public double[] getDoubleArray(int columnIndex) {
373424
checkNonNullOfType(columnIndex, Type.array(Type.float64()), columnIndex);

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

+36
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@ public long getLong(String columnName) {
125125
return delegate.get().getLong(columnName);
126126
}
127127

128+
@Override
129+
public float getFloat(int columnIndex) {
130+
checkValidState();
131+
return delegate.get().getFloat(columnIndex);
132+
}
133+
134+
@Override
135+
public float getFloat(String columnName) {
136+
checkValidState();
137+
return delegate.get().getFloat(columnName);
138+
}
139+
128140
@Override
129141
public double getDouble(int columnIndex) {
130142
checkValidState();
@@ -267,6 +279,30 @@ public List<Long> getLongList(String columnName) {
267279
return delegate.get().getLongList(columnName);
268280
}
269281

282+
@Override
283+
public float[] getFloatArray(int columnIndex) {
284+
checkValidState();
285+
return delegate.get().getFloatArray(columnIndex);
286+
}
287+
288+
@Override
289+
public float[] getFloatArray(String columnName) {
290+
checkValidState();
291+
return delegate.get().getFloatArray(columnName);
292+
}
293+
294+
@Override
295+
public List<Float> getFloatList(int columnIndex) {
296+
checkValidState();
297+
return delegate.get().getFloatList(columnIndex);
298+
}
299+
300+
@Override
301+
public List<Float> getFloatList(String columnName) {
302+
checkValidState();
303+
return delegate.get().getFloatList(columnName);
304+
}
305+
270306
@Override
271307
public double[] getDoubleArray(int columnIndex) {
272308
checkValidState();

0 commit comments

Comments
 (0)