Skip to content

Commit d313e3e

Browse files
deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.92.0 (#2032)
* deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.92.0 * feat: add support for UUID data type --------- Co-authored-by: Knut Olav Løite <[email protected]>
1 parent d5b88db commit d313e3e

File tree

13 files changed

+228
-48
lines changed

13 files changed

+228
-48
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
<dependency>
6262
<groupId>com.google.cloud</groupId>
6363
<artifactId>google-cloud-spanner-bom</artifactId>
64-
<version>6.91.1</version>
64+
<version>6.92.0</version>
6565
<type>pom</type>
6666
<scope>import</scope>
6767
</dependency>

samples/spring-data-jdbc/googlesql/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<dependency>
3131
<groupId>com.google.cloud</groupId>
3232
<artifactId>google-cloud-spanner-bom</artifactId>
33-
<version>6.91.1</version>
33+
<version>6.92.0</version>
3434
<scope>import</scope>
3535
<type>pom</type>
3636
</dependency>

samples/spring-data-jdbc/postgresql/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<dependency>
3131
<groupId>com.google.cloud</groupId>
3232
<artifactId>google-cloud-spanner-bom</artifactId>
33-
<version>6.91.1</version>
33+
<version>6.92.0</version>
3434
<scope>import</scope>
3535
<type>pom</type>
3636
</dependency>

samples/spring-data-mybatis/googlesql/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
<dependency>
3636
<groupId>com.google.cloud</groupId>
3737
<artifactId>google-cloud-spanner-bom</artifactId>
38-
<version>6.91.1</version>
38+
<version>6.92.0</version>
3939
<scope>import</scope>
4040
<type>pom</type>
4141
</dependency>

src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.HashSet;
3030
import java.util.List;
3131
import java.util.Set;
32+
import java.util.UUID;
3233

3334
/** Enum for mapping Cloud Spanner data types to Java classes and JDBC SQL {@link Types}. */
3435
enum JdbcDataType {
@@ -379,6 +380,32 @@ public Type getSpannerType() {
379380
return Type.timestamp();
380381
}
381382
},
383+
UUID {
384+
@Override
385+
public int getSqlType() {
386+
return UuidType.VENDOR_TYPE_NUMBER;
387+
}
388+
389+
@Override
390+
public Class<UUID> getJavaClass() {
391+
return UUID.class;
392+
}
393+
394+
@Override
395+
public Code getCode() {
396+
return Code.UUID;
397+
}
398+
399+
@Override
400+
public List<UUID> getArrayElements(ResultSet rs, int columnIndex) {
401+
return rs.getUuidList(columnIndex);
402+
}
403+
404+
@Override
405+
public Type getSpannerType() {
406+
return Type.uuid();
407+
}
408+
},
382409
STRUCT {
383410
@Override
384411
public int getSqlType() {

src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,12 @@ private Builder setParamWithUnknownType(ValueBinder<Builder> binder, Object valu
729729
} else if (Time.class.isAssignableFrom(value.getClass())) {
730730
Time timeValue = (Time) value;
731731
return binder.to(JdbcTypeConverter.toGoogleTimestamp(new Timestamp(timeValue.getTime())));
732+
} else if (UUID.class.isAssignableFrom(value.getClass())) {
733+
// Bind UUID values as untyped strings to allow them to be used with all types that support
734+
// string values (e.g. STRING, UUID).
735+
return binder.to(
736+
Value.untyped(
737+
com.google.protobuf.Value.newBuilder().setStringValue(value.toString()).build()));
732738
} else if (String.class.isAssignableFrom(value.getClass())) {
733739
String stringVal = (String) value;
734740
return binder.to(stringVal);
@@ -853,6 +859,9 @@ private Builder setArrayValue(ValueBinder<Builder> binder, int type, Object valu
853859
com.google.protobuf.Value.newBuilder()
854860
.setNullValue(NullValue.NULL_VALUE)
855861
.build()));
862+
case UuidType.VENDOR_TYPE_NUMBER:
863+
case UuidType.SHORT_VENDOR_TYPE_NUMBER:
864+
return binder.toUuidArray(null);
856865
default:
857866
return binder.to(
858867
Value.untyped(
@@ -907,6 +916,8 @@ private Builder setArrayValue(ValueBinder<Builder> binder, int type, Object valu
907916
return binder.toDateArray(JdbcTypeConverter.toGoogleDates((Date[]) value));
908917
} else if (Timestamp[].class.isAssignableFrom(value.getClass())) {
909918
return binder.toTimestampArray(JdbcTypeConverter.toGoogleTimestamps((Timestamp[]) value));
919+
} else if (UUID[].class.isAssignableFrom(value.getClass())) {
920+
return binder.toUuidArray(Arrays.asList((UUID[]) value));
910921
} else if (String[].class.isAssignableFrom(value.getClass())) {
911922
if (type == JsonType.VENDOR_TYPE_NUMBER || type == JsonType.SHORT_VENDOR_TYPE_NUMBER) {
912923
return binder.toJsonArray(Arrays.asList((String[]) value));

src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import java.util.List;
5353
import java.util.Map;
5454
import java.util.NoSuchElementException;
55+
import java.util.UUID;
5556
import javax.annotation.Nonnull;
5657

5758
/** Implementation of {@link ResultSet} for Cloud Spanner */
@@ -623,6 +624,38 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException {
623624
}
624625
}
625626

627+
public UUID getUUID(int columnIndex) throws SQLException {
628+
checkClosedAndValidRow();
629+
if (isNull(columnIndex)) {
630+
return null;
631+
}
632+
int spannerIndex = columnIndex - 1;
633+
Code type = getMainTypeCode(spanner.getColumnType(spannerIndex));
634+
switch (type) {
635+
case UUID:
636+
return spanner.getUuid(spannerIndex);
637+
case STRING:
638+
return UUID.fromString(spanner.getString(spannerIndex));
639+
case BYTES:
640+
case DATE:
641+
case TIMESTAMP:
642+
case BOOL:
643+
case FLOAT32:
644+
case FLOAT64:
645+
case INT64:
646+
case NUMERIC:
647+
case PG_NUMERIC:
648+
case JSON:
649+
case PG_JSONB:
650+
case STRUCT:
651+
case PROTO:
652+
case ENUM:
653+
case ARRAY:
654+
default:
655+
throw createInvalidToGetAs("uuid", type);
656+
}
657+
}
658+
626659
private InputStream getInputStream(String val, Charset charset) {
627660
if (val == null) return null;
628661
byte[] b = val.getBytes(charset);
@@ -764,35 +797,46 @@ public Object getObject(int columnIndex) throws SQLException {
764797
}
765798

766799
private Object getObject(Type type, int columnIndex) throws SQLException {
767-
// TODO: Refactor to check based on type code.
768-
if (type == Type.bool()) return getBoolean(columnIndex);
769-
if (type == Type.bytes()) return getBytes(columnIndex);
770-
if (type == Type.date()) return getDate(columnIndex);
771-
if (type == Type.float32()) {
772-
return getFloat(columnIndex);
773-
}
774-
if (type == Type.float64()) return getDouble(columnIndex);
775-
if (type == Type.int64() || type == Type.pgOid()) {
776-
return getLong(columnIndex);
777-
}
778-
if (type == Type.numeric()) return getBigDecimal(columnIndex);
779-
if (type == Type.pgNumeric()) {
780-
final String value = getString(columnIndex);
781-
try {
782-
return parseBigDecimal(value);
783-
} catch (Exception e) {
784-
return parseDouble(value);
785-
}
786-
}
787-
if (type == Type.string()) return getString(columnIndex);
788-
if (type == Type.json() || type == Type.pgJsonb()) {
789-
return getString(columnIndex);
800+
JdbcPreconditions.checkArgument(type != null, "type is null");
801+
switch (type.getCode()) {
802+
case BOOL:
803+
return getBoolean(columnIndex);
804+
case BYTES:
805+
case PROTO:
806+
return getBytes(columnIndex);
807+
case DATE:
808+
return getDate(columnIndex);
809+
case FLOAT32:
810+
return getFloat(columnIndex);
811+
case FLOAT64:
812+
return getDouble(columnIndex);
813+
case INT64:
814+
case PG_OID:
815+
case ENUM:
816+
return getLong(columnIndex);
817+
case NUMERIC:
818+
return getBigDecimal(columnIndex);
819+
case PG_NUMERIC:
820+
final String value = getString(columnIndex);
821+
try {
822+
return parseBigDecimal(value);
823+
} catch (Exception e) {
824+
return parseDouble(value);
825+
}
826+
case STRING:
827+
case JSON:
828+
case PG_JSONB:
829+
return getString(columnIndex);
830+
case TIMESTAMP:
831+
return getTimestamp(columnIndex);
832+
case UUID:
833+
return getUUID(columnIndex);
834+
case ARRAY:
835+
return getArray(columnIndex);
836+
default:
837+
throw JdbcSqlExceptionFactory.of(
838+
"Unknown type: " + type, com.google.rpc.Code.INVALID_ARGUMENT);
790839
}
791-
if (type == Type.timestamp()) return getTimestamp(columnIndex);
792-
if (type.getCode() == Code.PROTO) return getBytes(columnIndex);
793-
if (type.getCode() == Code.ENUM) return getLong(columnIndex);
794-
if (type.getCode() == Code.ARRAY) return getArray(columnIndex);
795-
throw JdbcSqlExceptionFactory.of("Unknown type: " + type, com.google.rpc.Code.INVALID_ARGUMENT);
796840
}
797841

798842
@Override

src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ static Object convert(Object value, Type type, Class<?> targetType) throws SQLEx
8282
if (value == null) {
8383
return null;
8484
}
85+
if (value.getClass().equals(targetType)) {
86+
return value;
87+
}
8588
try {
8689
if (targetType.equals(Value.class)) {
8790
return convertToSpannerValue(value, type);
@@ -370,7 +373,9 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx
370373

371374
private static void checkValidTypeAndValueForConvert(Type type, Object value)
372375
throws SQLException {
373-
if (value == null) return;
376+
if (value == null) {
377+
return;
378+
}
374379
JdbcPreconditions.checkArgument(
375380
type.getCode() != Code.ARRAY || Array.class.isAssignableFrom(value.getClass()),
376381
"input type is array, but input value is not an instance of java.sql.Array");
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.spanner.jdbc;
18+
19+
import com.google.spanner.v1.TypeCode;
20+
import java.sql.DatabaseMetaData;
21+
import java.sql.PreparedStatement;
22+
import java.sql.SQLType;
23+
24+
/**
25+
* Custom SQL type for Spanner UUID data type. This type (or the vendor type number) must be used
26+
* when setting a UUID parameter using {@link PreparedStatement#setObject(int, Object, SQLType)}.
27+
*/
28+
public class UuidType implements SQLType {
29+
public static final UuidType INSTANCE = new UuidType();
30+
/**
31+
* Spanner does not have any type numbers, but the code values are unique. Add 100,000 to avoid
32+
* conflicts with the type numbers in java.sql.Types.
33+
*/
34+
public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.UUID_VALUE;
35+
/**
36+
* Define a short type number as well, as this is what is expected to be returned in {@link
37+
* DatabaseMetaData#getTypeInfo()}.
38+
*/
39+
public static final short SHORT_VENDOR_TYPE_NUMBER = (short) VENDOR_TYPE_NUMBER;
40+
41+
private UuidType() {}
42+
43+
@Override
44+
public String getName() {
45+
return "UUID";
46+
}
47+
48+
@Override
49+
public String getVendor() {
50+
return UuidType.class.getPackage().getName();
51+
}
52+
53+
@Override
54+
public Integer getVendorTypeNumber() {
55+
return VENDOR_TYPE_NUMBER;
56+
}
57+
58+
public String toString() {
59+
return getName();
60+
}
61+
}

0 commit comments

Comments
 (0)