Skip to content

Commit 587e190

Browse files
committed
fix: accept Arrays of Integer, Short, Byte for Array<Int64>
1 parent 91688c7 commit 587e190

File tree

4 files changed

+109
-9
lines changed

4 files changed

+109
-9
lines changed

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

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,19 +92,41 @@ private JdbcArray(JdbcDataType type, Object[] elements) throws SQLException {
9292
this.data =
9393
java.lang.reflect.Array.newInstance(
9494
elements.getClass().getComponentType(), elements.length);
95+
System.arraycopy(elements, 0, this.data, 0, elements.length);
96+
} else if (type == JdbcDataType.INT64 && requiresWideningToLong(elements)) {
97+
// Convert Byte[], Short[], and Integer[] to Long[] for INT64 type
98+
// since Spanner only supports ARRAY<INT64>
99+
this.data = convertToLongArray(elements);
95100
} else {
96101
this.data = java.lang.reflect.Array.newInstance(type.getJavaClass(), elements.length);
102+
try {
103+
System.arraycopy(elements, 0, this.data, 0, elements.length);
104+
} catch (Exception e) {
105+
throw JdbcSqlExceptionFactory.of(
106+
"Could not copy array elements. Make sure the supplied array only contains elements of class "
107+
+ type.getJavaClass().getName(),
108+
Code.UNKNOWN,
109+
e);
110+
}
97111
}
98-
try {
99-
System.arraycopy(elements, 0, this.data, 0, elements.length);
100-
} catch (Exception e) {
101-
throw JdbcSqlExceptionFactory.of(
102-
"Could not copy array elements. Make sure the supplied array only contains elements of class "
103-
+ type.getJavaClass().getName(),
104-
Code.UNKNOWN,
105-
e);
112+
}
113+
}
114+
115+
private static boolean requiresWideningToLong(Object[] elements) {
116+
Class<?> componentType = elements.getClass().getComponentType();
117+
return componentType == Byte.class
118+
|| componentType == Short.class
119+
|| componentType == Integer.class;
120+
}
121+
122+
private static Long[] convertToLongArray(Object[] elements) {
123+
Long[] longElements = new Long[elements.length];
124+
for (int i = 0; i < elements.length; i++) {
125+
if (elements[i] != null) {
126+
longElements[i] = ((Number) elements[i]).longValue();
106127
}
107128
}
129+
return longElements;
108130
}
109131

110132
private JdbcArray(JdbcDataType type, List<?> elements) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ public Set<String> getPostgreSQLAliases() {
201201
},
202202
INT64 {
203203
private final Set<Class<?>> classes =
204-
new HashSet<>(Arrays.asList(Byte.class, Integer.class, Long.class));
204+
new HashSet<>(Arrays.asList(Byte.class, Short.class, Integer.class, Long.class));
205205

206206
@Override
207207
public int getSqlType() {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,8 @@ private Builder setArrayValue(ValueBinder<Builder> binder, int type, Object valu
875875
return binder.toBoolArray((boolean[]) value);
876876
} else if (Boolean[].class.isAssignableFrom(value.getClass())) {
877877
return binder.toBoolArray(Arrays.asList((Boolean[]) value));
878+
} else if (Byte[].class.isAssignableFrom(value.getClass())) {
879+
return binder.toInt64Array(toLongList((Byte[]) value));
878880
} else if (short[].class.isAssignableFrom(value.getClass())) {
879881
long[] l = new long[((short[]) value).length];
880882
for (int i = 0; i < l.length; i++) {

src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,82 @@ public void testCreateArrayTypeName() throws SQLException {
144144
assertThat(rs.next()).isFalse();
145145
}
146146

147+
// Test that Byte[] arrays are automatically widened to Long[] for INT64 type
148+
Long[] data;
149+
array = JdbcArray.createArray("INT64", new Byte[] {1, 2, 3, null, Byte.MAX_VALUE});
150+
assertThat(array.getBaseType()).isEqualTo(Types.BIGINT);
151+
// Data should be stored as Long[]
152+
assertThat(array.getArray()).isInstanceOf(Long[].class);
153+
data = (Long[]) array.getArray();
154+
assertThat(data[0]).isEqualTo(1L);
155+
assertThat(data[1]).isEqualTo(2L);
156+
assertThat(data[2]).isEqualTo(3L);
157+
assertThat(data[3]).isNull();
158+
assertThat(data[4]).isEqualTo((long) Byte.MAX_VALUE);
159+
160+
try (ResultSet rs = array.getResultSet()) {
161+
assertThat(rs.next()).isTrue();
162+
assertThat(rs.getByte(2)).isEqualTo((byte) 1);
163+
assertThat(rs.next()).isTrue();
164+
assertThat(rs.getByte(2)).isEqualTo((byte) 2);
165+
assertThat(rs.next()).isTrue();
166+
assertThat(rs.getByte(2)).isEqualTo((byte) 3);
167+
assertThat(rs.next()).isTrue();
168+
assertThat(rs.getByte(2)).isEqualTo((byte) 0);
169+
assertTrue(rs.wasNull());
170+
assertThat(rs.next()).isTrue();
171+
assertThat(rs.getByte(2)).isEqualTo(Byte.MAX_VALUE);
172+
assertThat(rs.next()).isFalse();
173+
}
174+
175+
// Test that Short[] arrays are automatically widened to Long[] for INT64 type
176+
array = JdbcArray.createArray("INT64", new Short[] {100, 200, null, Short.MAX_VALUE});
177+
assertThat(array.getBaseType()).isEqualTo(Types.BIGINT);
178+
// Data should be stored as Long[]
179+
assertThat(array.getArray()).isInstanceOf(Long[].class);
180+
data = (Long[]) array.getArray();
181+
assertThat(data[0]).isEqualTo(100L);
182+
assertThat(data[1]).isEqualTo(200L);
183+
assertThat(data[2]).isNull();
184+
assertThat(data[3]).isEqualTo((long) Short.MAX_VALUE);
185+
186+
try (ResultSet rs = array.getResultSet()) {
187+
assertThat(rs.next()).isTrue();
188+
assertThat(rs.getShort(2)).isEqualTo((short) 100);
189+
assertThat(rs.next()).isTrue();
190+
assertThat(rs.getShort(2)).isEqualTo((short) 200);
191+
assertThat(rs.next()).isTrue();
192+
assertThat(rs.getShort(2)).isEqualTo((short) 0);
193+
assertTrue(rs.wasNull());
194+
assertThat(rs.next()).isTrue();
195+
assertThat(rs.getShort(2)).isEqualTo(Short.MAX_VALUE);
196+
assertThat(rs.next()).isFalse();
197+
}
198+
199+
// Test that Integer[] arrays are automatically widened to Long[] for INT64 type
200+
array = JdbcArray.createArray("INT64", new Integer[] {1000, 2000, null, Integer.MAX_VALUE});
201+
assertThat(array.getBaseType()).isEqualTo(Types.BIGINT);
202+
// Data should be stored as Long[]
203+
assertThat(array.getArray()).isInstanceOf(Long[].class);
204+
data = (Long[]) array.getArray();
205+
assertThat(data[0]).isEqualTo(1000L);
206+
assertThat(data[1]).isEqualTo(2000L);
207+
assertThat(data[2]).isNull();
208+
assertThat(data[3]).isEqualTo((long) Integer.MAX_VALUE);
209+
210+
try (ResultSet rs = array.getResultSet()) {
211+
assertThat(rs.next()).isTrue();
212+
assertThat(rs.getInt(2)).isEqualTo(1000);
213+
assertThat(rs.next()).isTrue();
214+
assertThat(rs.getInt(2)).isEqualTo(2000);
215+
assertThat(rs.next()).isTrue();
216+
assertThat(rs.getInt(2)).isEqualTo(0);
217+
assertTrue(rs.wasNull());
218+
assertThat(rs.next()).isTrue();
219+
assertThat(rs.getInt(2)).isEqualTo(Integer.MAX_VALUE);
220+
assertThat(rs.next()).isFalse();
221+
}
222+
147223
array =
148224
JdbcArray.createArray("NUMERIC", new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN});
149225
assertThat(array.getBaseType()).isEqualTo(Types.NUMERIC);

0 commit comments

Comments
 (0)