Skip to content

Commit 45c2059

Browse files
chore: Support text/varchar type in JDBC
1 parent ab8fcf9 commit 45c2059

File tree

5 files changed

+86
-5
lines changed

5 files changed

+86
-5
lines changed

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,11 @@ class JdbcArray implements Array {
6060
* the elements array is not compatible with the base type of the array.
6161
*/
6262
static JdbcArray createArray(String typeName, Object[] elements) throws SQLException {
63-
for (JdbcDataType type : JdbcDataType.values()) {
64-
if (type.getTypeName().equalsIgnoreCase(typeName)) {
65-
return new JdbcArray(type, elements);
63+
if (typeName != null) {
64+
for (JdbcDataType type : JdbcDataType.values()) {
65+
if (type.matches(typeName)) {
66+
return new JdbcArray(type, elements);
67+
}
6668
}
6769
}
6870
throw JdbcSqlExceptionFactory.of(
@@ -91,7 +93,14 @@ private JdbcArray(JdbcDataType type, Object[] elements) throws SQLException {
9193
java.lang.reflect.Array.newInstance(
9294
elements.getClass().getComponentType(), elements.length);
9395
} else {
94-
this.data = java.lang.reflect.Array.newInstance(type.getJavaClass(), elements.length);
96+
// If elements contains the type of supported classes(or Java types) then
97+
// We should allow it set it in the PreparedStatement
98+
Class<?> clazz = type.getJavaClass();
99+
if (elements.length > 0
100+
&& type.getSupportedJavaClasses().contains(elements[0].getClass())) {
101+
clazz = elements[0].getClass();
102+
}
103+
this.data = java.lang.reflect.Array.newInstance(clazz, elements.length);
95104
}
96105
try {
97106
System.arraycopy(elements, 0, this.data, 0, elements.length);

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.google.cloud.spanner.jdbc;
1818

19+
import com.google.cloud.spanner.Dialect;
1920
import com.google.cloud.spanner.ResultSet;
2021
import com.google.cloud.spanner.Struct;
2122
import com.google.cloud.spanner.Type;
@@ -24,6 +25,7 @@
2425
import java.sql.Date;
2526
import java.sql.Timestamp;
2627
import java.sql.Types;
28+
import java.time.LocalDate;
2729
import java.util.Arrays;
2830
import java.util.Collections;
2931
import java.util.HashSet;
@@ -86,6 +88,8 @@ public Type getSpannerType() {
8688
}
8789
},
8890
DATE {
91+
private final Set<Class<?>> classes = new HashSet<>(Arrays.asList(Date.class, LocalDate.class));
92+
8993
@Override
9094
public int getSqlType() {
9195
return Types.DATE;
@@ -96,6 +100,11 @@ public Class<Date> getJavaClass() {
96100
return Date.class;
97101
}
98102

103+
@Override
104+
public Set<? extends Class<?>> getSupportedJavaClasses() {
105+
return classes;
106+
}
107+
99108
@Override
100109
public Code getCode() {
101110
return Code.DATE;
@@ -154,6 +163,7 @@ public Type getSpannerType() {
154163
},
155164
FLOAT64 {
156165
private final Set<Class<?>> classes = new HashSet<>(Arrays.asList(Float.class, Double.class));
166+
private final Set<String> aliases = new HashSet<>(Collections.singletonList("float8"));
157167

158168
@Override
159169
public int getSqlType() {
@@ -184,6 +194,11 @@ public List<Double> getArrayElements(ResultSet rs, int columnIndex) {
184194
public Type getSpannerType() {
185195
return Type.float64();
186196
}
197+
198+
@Override
199+
public Set<String> getAliases() {
200+
return aliases;
201+
}
187202
},
188203
INT64 {
189204
private final Set<Class<?>> classes =
@@ -220,6 +235,9 @@ public Type getSpannerType() {
220235
}
221236
},
222237
NUMERIC {
238+
239+
private final Set<String> aliases = new HashSet<>(Collections.singletonList("decimal"));
240+
223241
@Override
224242
public int getSqlType() {
225243
return Types.NUMERIC;
@@ -244,6 +262,11 @@ public List<BigDecimal> getArrayElements(ResultSet rs, int columnIndex) {
244262
public Type getSpannerType() {
245263
return Type.numeric();
246264
}
265+
266+
@Override
267+
public Set<String> getAliases() {
268+
return aliases;
269+
}
247270
},
248271
PG_NUMERIC {
249272
@Override
@@ -272,6 +295,8 @@ public Type getSpannerType() {
272295
}
273296
},
274297
STRING {
298+
private final Set<String> aliases = new HashSet<>(Arrays.asList("varchar", "text"));
299+
275300
@Override
276301
public int getSqlType() {
277302
return Types.NVARCHAR;
@@ -296,6 +321,11 @@ public List<String> getArrayElements(ResultSet rs, int columnIndex) {
296321
public Type getSpannerType() {
297322
return Type.string();
298323
}
324+
325+
@Override
326+
public Set<String> getAliases() {
327+
return aliases;
328+
}
299329
},
300330
JSON {
301331
@Override
@@ -498,6 +528,21 @@ public Type getSpannerType() {
498528

499529
public abstract Type getSpannerType();
500530

531+
public Set<String> getAliases() {
532+
return Collections.emptySet();
533+
}
534+
535+
/***
536+
* @param typeName type of the column
537+
* @return true if type name matches current type name or matches with one of postgres aliases
538+
* or if it matches equivalent postgres type.
539+
*/
540+
public boolean matches(String typeName) {
541+
return getTypeName().equalsIgnoreCase(typeName)
542+
|| getAliases().contains(typeName.toLowerCase())
543+
|| getSpannerType().getSpannerTypeName(Dialect.POSTGRESQL).equalsIgnoreCase(typeName);
544+
}
545+
501546
// TODO: Implement and use this method for all types.
502547
public int getPrecision() {
503548
throw new UnsupportedOperationException();

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,8 @@ private Builder setArrayValue(ValueBinder<Builder> binder, int type, Object valu
914914
}
915915
} else if (Date[].class.isAssignableFrom(value.getClass())) {
916916
return binder.toDateArray(JdbcTypeConverter.toGoogleDates((Date[]) value));
917+
} else if (LocalDate[].class.isAssignableFrom(value.getClass())) {
918+
return binder.toDateArray(JdbcTypeConverter.toGoogleDates((LocalDate[]) value));
917919
} else if (Timestamp[].class.isAssignableFrom(value.getClass())) {
918920
return binder.toTimestampArray(JdbcTypeConverter.toGoogleTimestamps((Timestamp[]) value));
919921
} else if (UUID[].class.isAssignableFrom(value.getClass())) {

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,10 @@ static Date toGoogleDate(java.sql.Time date) {
425425
return Date.fromYearMonthDay(1970, 1, 1);
426426
}
427427

428+
static Date toGoogleDate(LocalDate date) {
429+
return Date.fromYearMonthDay(date.getYear(), date.getMonthValue(), date.getDayOfMonth());
430+
}
431+
428432
@SuppressWarnings("deprecation")
429433
static Date toGoogleDate(java.sql.Timestamp date) {
430434
return date == null
@@ -440,6 +444,14 @@ static List<Date> toGoogleDates(java.sql.Date[] dates) {
440444
return res;
441445
}
442446

447+
static List<Date> toGoogleDates(LocalDate[] dates) {
448+
List<com.google.cloud.Date> res = new ArrayList<>(dates.length);
449+
for (LocalDate date : dates) {
450+
res.add(toGoogleDate(date));
451+
}
452+
return res;
453+
}
454+
443455
static java.sql.Date toSqlDate(Date date) {
444456
return toSqlDate(date, Calendar.getInstance());
445457
}

src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,20 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A
2828
WHEN DATA_TYPE = 'jsonb' THEN -9
2929
WHEN DATA_TYPE = 'timestamp with time zone' THEN 93
3030
END AS "DATA_TYPE",
31-
DATA_TYPE AS "TYPE_NAME",
31+
CASE
32+
WHEN DATA_TYPE LIKE 'ARRAY' THEN
33+
CASE
34+
WHEN spanner_type LIKE '%[]' THEN
35+
CONCAT('_',
36+
REPLACE(
37+
REPLACE(
38+
REPLACE(spanner_type, '[]', ''),
39+
'character varying', 'varchar'),
40+
'boolean', 'bool'))
41+
ELSE spanner_type
42+
END
43+
ELSE DATA_TYPE
44+
END AS "TYPE_NAME",
3245
CASE
3346
WHEN DATA_TYPE LIKE 'ARRAY' THEN 0
3447
WHEN DATA_TYPE = 'boolean' THEN NULL

0 commit comments

Comments
 (0)