fix(jdbc): preserve multi-bit values when reading booleans

This commit is contained in:
Andrew
2026-08-13 23:57:30 +08:00
committed by GitHub
parent 4efd815329
commit b22cd9079a
2 changed files with 69 additions and 0 deletions
@@ -3026,11 +3026,24 @@ public final class DbxJdbcPlugin {
int index,
boolean preserveOracleDateTime
) throws SQLException {
int columnType = meta.getColumnType(index);
if (columnType == Types.BOOLEAN) {
boolean boolValue = rs.getBoolean(index);
if (!rs.wasNull()) {
return boolValue;
}
return null;
}
Object value = rs.getObject(index);
if (value == null) {
return null;
}
if (value instanceof byte[] bytes) {
if (columnType == Types.BIT && bytes.length == 1 && (bytes[0] == 't' || bytes[0] == 'f')) {
return bytes[0] == 't';
}
return binaryToHex(bytes);
}
if (value instanceof Clob clob) {
@@ -425,6 +425,39 @@ final class DbxJdbcPluginTest {
assertEquals("GaussDB CLOB 中文内容", method.invoke(null, rs, columnMeta(Types.CLOB), 1, false));
}
@Test
void readValueConvertsGaussDbBooleanBytesWithoutCollapsingMultiBitValues() throws Exception {
Method method = DbxJdbcPlugin.class.getDeclaredMethod(
"readValue",
ResultSet.class,
ResultSetMetaData.class,
int.class,
boolean.class
);
method.setAccessible(true);
assertEquals(true, method.invoke(null, objectResultSet(new byte[] { 't' }), columnMeta(Types.BIT), 1, false));
assertEquals(false, method.invoke(null, objectResultSet(new byte[] { 'f' }), columnMeta(Types.BIT), 1, false));
assertEquals(null, method.invoke(null, objectResultSet(null), columnMeta(Types.BIT), 1, false));
assertEquals("0x0102", method.invoke(null, objectResultSet(new byte[] { 1, 2 }), columnMeta(Types.BIT), 1, false));
}
@Test
void readValueUsesJdbcBooleanAccessForBooleanColumns() throws Exception {
Method method = DbxJdbcPlugin.class.getDeclaredMethod(
"readValue",
ResultSet.class,
ResultSetMetaData.class,
int.class,
boolean.class
);
method.setAccessible(true);
assertEquals(true, method.invoke(null, booleanResultSet(true), columnMeta(Types.BOOLEAN), 1, false));
assertEquals(false, method.invoke(null, booleanResultSet(false), columnMeta(Types.BOOLEAN), 1, false));
assertEquals(null, method.invoke(null, booleanResultSet(null), columnMeta(Types.BOOLEAN), 1, false));
}
@Test
void executeQueryPreservesOracleDateTimeComponent() throws Exception {
List<String> calls = new ArrayList<>();
@@ -2192,6 +2225,29 @@ final class DbxJdbcPluginTest {
);
}
private static ResultSet objectResultSet(Object value) {
return (ResultSet) Proxy.newProxyInstance(
DbxJdbcPluginTest.class.getClassLoader(),
new Class<?>[] { ResultSet.class },
(proxy, method, args) -> switch (method.getName()) {
case "getObject" -> value;
default -> defaultValue(method.getReturnType());
}
);
}
private static ResultSet booleanResultSet(Boolean value) {
return (ResultSet) Proxy.newProxyInstance(
DbxJdbcPluginTest.class.getClassLoader(),
new Class<?>[] { ResultSet.class },
(proxy, method, args) -> switch (method.getName()) {
case "getBoolean" -> Boolean.TRUE.equals(value);
case "wasNull" -> value == null;
default -> defaultValue(method.getReturnType());
}
);
}
private static DatabaseMetaData tableTypesMeta(String... types) {
return (DatabaseMetaData) Proxy.newProxyInstance(
DbxJdbcPluginTest.class.getClassLoader(),