From 0c293b84b1b218a87c224c0ff1b9115f36361127 Mon Sep 17 00:00:00 2001 From: Min Zhu Date: Mon, 11 Mar 2024 15:55:42 -0400 Subject: [PATCH] fix: upgrade libraries-bom to 26.34.0 and add spanner support float32 type (#2662) * deps: bump com.google.cloud:libraries-bom from 26.33.0 to 26.34.0 Bumps [com.google.cloud:libraries-bom](https://github.com/googleapis/java-cloud-bom) from 26.33.0 to 26.34.0. - [Release notes](https://github.com/googleapis/java-cloud-bom/releases) - [Changelog](https://github.com/googleapis/java-cloud-bom/blob/main/release-please-config.json) - [Commits](https://github.com/googleapis/java-cloud-bom/compare/v26.33.0...v26.34.0) --- updated-dependencies: - dependency-name: com.google.cloud:libraries-bom dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * feat(spanner): support float32 type. * chore: add unit tests for float32. * fix: add float32 to type mapper and corresponding unit tests. --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- ...verterAwareMappingSpannerEntityWriter.java | 4 +++ .../core/convert/SpannerTypeMapper.java | 3 ++ .../spanner/core/convert/StructAccessor.java | 7 ++++ .../core/admin/SpannerSchemaUtilsTests.java | 33 +++++++++++++++---- ...areMappingSpannerEntityProcessorTests.java | 20 +++++++++++ ...rAwareMappingSpannerEntityWriterTests.java | 20 +++++++++++ .../spanner/core/convert/TestEntities.java | 6 ++++ spring-cloud-gcp-dependencies/pom.xml | 2 +- 8 files changed, 87 insertions(+), 8 deletions(-) diff --git a/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityWriter.java b/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityWriter.java index fc08b52651..1dc3685ebf 100644 --- a/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityWriter.java +++ b/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityWriter.java @@ -80,6 +80,7 @@ private static Map, BiConsumer, Iterable>> createIterabl map.put(Boolean.class, ValueBinder::toBoolArray); map.put(Long.class, ValueBinder::toInt64Array); map.put(Double.class, ValueBinder::toFloat64Array); + map.put(Float.class, ValueBinder::toFloat32Array); map.put(BigDecimal.class, ValueBinder::toNumericArray); map.put(Timestamp.class, ValueBinder::toTimestampArray); map.put(Date.class, ValueBinder::toDateArray); @@ -97,12 +98,15 @@ private static Map, BiConsumer, Iterable>> createIterabl map.put(long.class, (BiFunction) ValueBinder::to); map.put(Double.class, (BiFunction) ValueBinder::to); map.put(double.class, (BiFunction) ValueBinder::to); + map.put(Float.class, (BiFunction) ValueBinder::to); + map.put(float.class, (BiFunction) ValueBinder::to); map.put(BigDecimal.class, (BiFunction) ValueBinder::to); map.put(Timestamp.class, (BiFunction) ValueBinder::to); map.put(Date.class, (BiFunction) ValueBinder::to); map.put(ByteArray.class, (BiFunction) ValueBinder::to); map.put(String.class, (BiFunction) ValueBinder::to); map.put(double[].class, (BiFunction) ValueBinder::toFloat64Array); + map.put(float[].class, (BiFunction) ValueBinder::toFloat32Array); map.put(boolean[].class, (BiFunction) ValueBinder::toBoolArray); map.put(long[].class, (BiFunction) ValueBinder::toInt64Array); map.put(Struct.class, (BiFunction) ValueBinder::to); diff --git a/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/SpannerTypeMapper.java b/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/SpannerTypeMapper.java index e94b80330f..0a1341f0c5 100644 --- a/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/SpannerTypeMapper.java +++ b/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/SpannerTypeMapper.java @@ -46,6 +46,7 @@ private SpannerTypeMapper() {} .put(Type.Code.BYTES, ByteArray.class) .put(Type.Code.DATE, com.google.cloud.Date.class) .put(Type.Code.FLOAT64, Double.class) + .put(Type.Code.FLOAT32, Float.class) .put(Type.Code.NUMERIC, BigDecimal.class) .put(Type.Code.INT64, Long.class) .put(Type.Code.STRING, String.class) @@ -59,6 +60,7 @@ private SpannerTypeMapper() {} .put(Type.Code.BYTES, ByteArray[].class) .put(Type.Code.DATE, com.google.cloud.Date[].class) .put(Type.Code.FLOAT64, double[].class) + .put(Type.Code.FLOAT32, float[].class) .put(Type.Code.NUMERIC, BigDecimal[].class) .put(Type.Code.INT64, long[].class) .put(Type.Code.STRING, String[].class) @@ -74,6 +76,7 @@ private SpannerTypeMapper() {} type -> builderMap.put(SPANNER_SIMPLE_COLUMN_CODES_TO_JAVA_TYPE_MAPPING.get(type), type)); builderMap.put(double.class, Code.FLOAT64); + builderMap.put(float.class, Code.FLOAT32); builderMap.put(long.class, Code.INT64); JAVA_TYPE_TO_SPANNER_SIMPLE_COLUMN_TYPE_MAPPING = Collections.unmodifiableMap(builderMap); } diff --git a/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/StructAccessor.java b/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/StructAccessor.java index ed578db6f3..72c09fadaf 100644 --- a/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/StructAccessor.java +++ b/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/StructAccessor.java @@ -49,6 +49,7 @@ public class StructAccessor { .put(Long.class, AbstractStructReader::getLongList) .put(String.class, AbstractStructReader::getStringList) .put(Double.class, AbstractStructReader::getDoubleList) + .put(Float.class, AbstractStructReader::getFloatList) .put(Timestamp.class, AbstractStructReader::getTimestampList) .put(Date.class, AbstractStructReader::getDateList) .put(ByteArray.class, AbstractStructReader::getBytesList) @@ -64,11 +65,14 @@ public class StructAccessor { .put(String.class, AbstractStructReader::getString) .put(Double.class, AbstractStructReader::getDouble) .put(double.class, AbstractStructReader::getDouble) + .put(Float.class, AbstractStructReader::getFloat) + .put(float.class, AbstractStructReader::getFloat) .put(Timestamp.class, AbstractStructReader::getTimestamp) .put(Date.class, AbstractStructReader::getDate) .put(BigDecimal.class, AbstractStructReader::getBigDecimal) .put(ByteArray.class, AbstractStructReader::getBytes) .put(double[].class, AbstractStructReader::getDoubleArray) + .put(float[].class, AbstractStructReader::getFloatArray) .put(long[].class, AbstractStructReader::getLongArray) .put(boolean[].class, AbstractStructReader::getBooleanArray) // Note that Struct.class appears in this map. While we support @@ -85,11 +89,14 @@ public class StructAccessor { .put(String.class, AbstractStructReader::getString) .put(Double.class, AbstractStructReader::getDouble) .put(double.class, AbstractStructReader::getDouble) + .put(Float.class, AbstractStructReader::getFloat) + .put(float.class, AbstractStructReader::getFloat) .put(Timestamp.class, AbstractStructReader::getTimestamp) .put(Date.class, AbstractStructReader::getDate) .put(BigDecimal.class, AbstractStructReader::getBigDecimal) .put(ByteArray.class, AbstractStructReader::getBytes) .put(double[].class, AbstractStructReader::getDoubleArray) + .put(float[].class, AbstractStructReader::getFloatArray) .put(long[].class, AbstractStructReader::getLongArray) .put(boolean[].class, AbstractStructReader::getBooleanArray) // Note that Struct.class appears in this map. While we support diff --git a/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/admin/SpannerSchemaUtilsTests.java b/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/admin/SpannerSchemaUtilsTests.java index 18cb75b291..02fa5d67e3 100644 --- a/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/admin/SpannerSchemaUtilsTests.java +++ b/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/admin/SpannerSchemaUtilsTests.java @@ -68,13 +68,15 @@ void getDropDdlTest() { @Test void getCreateDdlTest() { String ddlResult = - "CREATE TABLE custom_test_table ( id STRING(MAX) , id3 INT64 , id_2 STRING(MAX) , bytes2" - + " BYTES(MAX) , custom_col FLOAT64 NOT NULL , other STRING(333) , primitiveDoubleField" - + " FLOAT64 , bigDoubleField FLOAT64 , bigLongField INT64 , primitiveIntField INT64 ," - + " bigIntField INT64 , bytes BYTES(MAX) , bytesList ARRAY , integerList" - + " ARRAY , doubles ARRAY , commitTimestamp TIMESTAMP OPTIONS" - + " (allow_commit_timestamp=true) , bigDecimalField NUMERIC , bigDecimals" - + " ARRAY , jsonCol JSON ) PRIMARY KEY ( id , id_2 , id3 )"; + "CREATE TABLE custom_test_table ( id STRING(MAX) , id3 INT64 , id_2 STRING(MAX) , " + + "bytes2 BYTES(MAX) , custom_col FLOAT64 NOT NULL , other STRING(333) , " + + "primitiveDoubleField FLOAT64 , bigDoubleField FLOAT64 , primitiveFloatField FLOAT32 , " + + "bigFloatField FLOAT32 , bigLongField INT64 , primitiveIntField INT64 , " + + "bigIntField INT64 , bytes BYTES(MAX) , bytesList ARRAY , " + + "integerList ARRAY , doubles ARRAY , floats ARRAY , " + + "commitTimestamp TIMESTAMP OPTIONS (allow_commit_timestamp=true) , " + + "bigDecimalField NUMERIC , bigDecimals ARRAY , jsonCol JSON ) " + + "PRIMARY KEY ( id , id_2 , id3 )"; assertThat(this.spannerSchemaUtils.getCreateTableDdlString(TestEntity.class)) .isEqualTo(ddlResult); @@ -157,6 +159,17 @@ void ddlForListOfListOfDoubles() { "doubleList ARRAY"); } + @Test + void ddlForListOfListOfFloats() { + assertColumnDdl( + List.class, + Float.class, + "floatList", + null, + OptionalLong.empty(), + "floatList ARRAY"); + } + @Test void createDdlForJson() { assertColumnDdl( @@ -260,6 +273,10 @@ private static class TestEntity { Double bigDoubleField; + float primitiveFloatField; + + Float bigFloatField; + Long bigLongField; int primitiveIntField; @@ -275,6 +292,8 @@ private static class TestEntity { double[] doubles; + float[] floats; + // this is intentionally a double to test that it is forced to be TIMESTAMP on Spanner // anyway @Column(spannerCommitTimestamp = true) diff --git a/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityProcessorTests.java b/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityProcessorTests.java index dda05cbce9..6469c66909 100644 --- a/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityProcessorTests.java +++ b/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityProcessorTests.java @@ -49,6 +49,7 @@ class ConverterAwareMappingSpannerEntityProcessorTests { private static final Offset DELTA = Offset.offset(0.00001); + private static final Offset DELTA_FLOAT = Offset.offset(0.00001F); private static final Converter SPANNER_TO_JAVA = new Converter() { @@ -183,6 +184,7 @@ private void verifyCanConvert( @Test void mapToListTest() { List doubleList = Collections.singletonList(3.33); + List floatList = Collections.singletonList(3.33F); List stringList = Collections.singletonList("string"); List instants = Arrays.asList( @@ -219,6 +221,12 @@ void mapToListTest() { .to(Value.float64Array(new double[] {3.33, 3.33, 3.33})) .set("doubleList") .to(Value.float64Array(doubleList)) + .set("floatField") + .to(Value.float32(3.33F)) + .set("floatArray") + .to(Value.float32Array(new float[] {3.33F, 3.33F, 3.33F})) + .set("floatList") + .to(Value.float32Array(floatList)) .set("stringList") .to(Value.stringArray(stringList)) .set("booleanList") @@ -273,6 +281,12 @@ void mapToListTest() { .to(Value.float64Array(new double[] {5.55, 5.55})) .set("doubleList") .to(Value.float64Array(doubleList)) + .set("floatField") + .to(Value.float32(5.55F)) + .set("floatArray") + .to(Value.float32Array(new float[] {5.55F, 5.55F})) + .set("floatList") + .to(Value.float32Array(floatList)) .set("stringList") .to(Value.stringArray(stringList)) .set("booleanList") @@ -337,6 +351,8 @@ void mapToListTest() { assertThat(t1.dateField.getYear()).isEqualTo(2018); assertThat(t1.doubleField).isEqualTo(3.33, DELTA); assertThat(t1.doubleArray).hasSize(3); + assertThat(t1.floatField).isEqualTo(3.33F, DELTA_FLOAT); + assertThat(t1.floatArray).hasSize(3); assertThat(t1.bigDecimals).containsExactly(BigDecimal.ONE, BigDecimal.ZERO); assertThat(t2) @@ -358,6 +374,10 @@ void mapToListTest() { assertThat(t2.doubleArray).hasSize(2); assertThat(t2.doubleList).hasSize(1); assertThat(t2.doubleList.get(0)).isEqualTo(3.33, DELTA); + assertThat(t2.floatField).isEqualTo(5.55F, DELTA_FLOAT); + assertThat(t2.floatArray).hasSize(2); + assertThat(t2.floatList).hasSize(1); + assertThat(t2.floatList.get(0)).isEqualTo(3.33F, DELTA_FLOAT); assertThat(t2.stringList).containsExactly("string"); assertThat(t2.bigDecimalField).isEqualTo(new BigDecimal("0.0001")); assertThat(t2.bigDecimals).containsExactly(new BigDecimal("-0.999"), new BigDecimal("10.9001")); diff --git a/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityWriterTests.java b/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityWriterTests.java index 9ee849d8d6..7bf52d7a98 100644 --- a/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityWriterTests.java +++ b/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityWriterTests.java @@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyDouble; +import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.isNull; @@ -97,6 +98,10 @@ void writeTest() { t.doubleArray = new double[] {3.33, 3.33, 3.33}; t.doubleList = new ArrayList<>(); t.doubleList.add(3.33); + t.floatField = 3.33F; + t.floatArray = new float[] {3.33F, 3.33F, 3.33F}; + t.floatList = new ArrayList<>(); + t.floatList.add(3.33F); t.stringList = new ArrayList<>(); t.stringList.add("stringstringstring"); t.dateField = Date.fromYearMonthDay(2018, 11, 22); @@ -192,6 +197,18 @@ void writeTest() { when(doubleListFieldBinder.toFloat64Array((Iterable) any())).thenReturn(null); when(writeBuilder.set("doubleList")).thenReturn(doubleListFieldBinder); + ValueBinder floatFieldBinder = mock(ValueBinder.class); + when(floatFieldBinder.to(anyFloat())).thenReturn(null); + when(writeBuilder.set("floatField")).thenReturn(floatFieldBinder); + + ValueBinder floatArrayFieldBinder = mock(ValueBinder.class); + when(floatArrayFieldBinder.toStringArray(any())).thenReturn(null); + when(writeBuilder.set("floatArray")).thenReturn(floatArrayFieldBinder); + + ValueBinder floatListFieldBinder = mock(ValueBinder.class); + when(floatListFieldBinder.toFloat32Array((Iterable) any())).thenReturn(null); + when(writeBuilder.set("floatList")).thenReturn(floatListFieldBinder); + ValueBinder stringListFieldBinder = mock(ValueBinder.class); when(stringListFieldBinder.toStringArray(any())).thenReturn(null); when(writeBuilder.set("stringList")).thenReturn(stringListFieldBinder); @@ -257,6 +274,9 @@ void writeTest() { verify(doubleFieldBinder, times(1)).to(Double.valueOf(t.doubleField)); verify(doubleArrayFieldBinder, times(1)).to("3.33,3.33,3.33"); verify(doubleListFieldBinder, times(1)).toFloat64Array(t.doubleList); + verify(floatFieldBinder, times(1)).to(Float.valueOf(t.floatField)); + verify(floatArrayFieldBinder, times(1)).to("3.33,3.33,3.33"); + verify(floatListFieldBinder, times(1)).toFloat32Array(t.floatList); verify(stringListFieldBinder, times(1)).toStringArray(t.stringList); verify(booleanListFieldBinder, times(1)).toBoolArray(t.booleanList); verify(longListFieldBinder, times(1)).toStringArray(any()); diff --git a/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/TestEntities.java b/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/TestEntities.java index 9354479923..5808aec792 100644 --- a/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/TestEntities.java +++ b/spring-cloud-gcp-data-spanner/src/test/java/com/google/cloud/spring/data/spanner/core/convert/TestEntities.java @@ -56,15 +56,21 @@ static class TestEntity { long longField; double doubleField; + float floatField; // This double array is forced to be stored as a String for testing @Column(spannerType = TypeCode.STRING) double[] doubleArray; + // This double array is forced to be stored as a String for testing + @Column(spannerType = TypeCode.STRING) + float[] floatArray; + // int is not a native Cloud Spanner type, so this will utilize custom conversions. int intField; List doubleList; + List floatList; List stringList; diff --git a/spring-cloud-gcp-dependencies/pom.xml b/spring-cloud-gcp-dependencies/pom.xml index e246a2b04c..1a6771e009 100644 --- a/spring-cloud-gcp-dependencies/pom.xml +++ b/spring-cloud-gcp-dependencies/pom.xml @@ -34,7 +34,7 @@ - 26.33.0 + 26.34.0 1.14.1 1.0.4.RELEASE 1.3.0