diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index f9e9376421..89acbc938b 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -14,6 +14,6 @@ - Databricks SDK dependency upgraded to latest version 0.60.0 ### Fixed -- +- Fixed `ResultSet.getString` for Boolean columns in Metadata result set. --- *Note: When making changes, please add your change under the appropriate section with a brief description.* diff --git a/src/main/java/com/databricks/jdbc/api/impl/converters/BitConverter.java b/src/main/java/com/databricks/jdbc/api/impl/converters/BitConverter.java index 5d0947ed29..41ddf4fd63 100644 --- a/src/main/java/com/databricks/jdbc/api/impl/converters/BitConverter.java +++ b/src/main/java/com/databricks/jdbc/api/impl/converters/BitConverter.java @@ -17,7 +17,18 @@ public boolean toBoolean(Object object) throws DatabricksSQLException { return Boolean.parseBoolean((String) object); } throw new DatabricksSQLException( - "Unsupported type for conversion to BIT: " + object.getClass(), + "Unsupported type for conversion to BIT: " + (object == null ? "null" : object.getClass()), + DatabricksDriverErrorCode.UNSUPPORTED_OPERATION); + } + + @Override + public String toString(Object object) throws DatabricksSQLException { + if (object instanceof Boolean) { + return object.toString(); + } + throw new DatabricksSQLException( + "Unsupported type for conversion to String: " + + (object == null ? "null" : object.getClass()), DatabricksDriverErrorCode.UNSUPPORTED_OPERATION); } } diff --git a/src/test/java/com/databricks/jdbc/api/impl/converters/BitConverterTest.java b/src/test/java/com/databricks/jdbc/api/impl/converters/BitConverterTest.java new file mode 100644 index 0000000000..4245da9030 --- /dev/null +++ b/src/test/java/com/databricks/jdbc/api/impl/converters/BitConverterTest.java @@ -0,0 +1,126 @@ +package com.databricks.jdbc.api.impl.converters; + +import static org.junit.jupiter.api.Assertions.*; + +import com.databricks.jdbc.exception.DatabricksSQLException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +public class BitConverterTest { + + private final BitConverter bitConverter = new BitConverter(); + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void testToStringWithBooleanPrimitives(boolean input) throws DatabricksSQLException { + String expected = input ? "true" : "false"; + assertEquals(expected, bitConverter.toString(input)); + } + + @ParameterizedTest + @CsvSource({"true, true", "false, false"}) + public void testToStringWithBooleanObjects(String input, String expected) + throws DatabricksSQLException { + Boolean booleanInput = Boolean.parseBoolean(input); + assertEquals(expected, bitConverter.toString(booleanInput)); + } + + @ParameterizedTest + @CsvSource({ + "null, null", + "Object, Object", + "int[], class [I", + "String[], class [Ljava.lang.String;" + }) + public void testToStringWithUnsupportedTypes(String typeDescription, String expectedInMessage) { + Object input = getTestObject(typeDescription); + + DatabricksSQLException exception = + assertThrows(DatabricksSQLException.class, () -> bitConverter.toString(input)); + + assertTrue(exception.getMessage().contains("Unsupported type for conversion to String")); + assertTrue(exception.getMessage().contains(expectedInMessage)); + assertEquals("UNSUPPORTED_OPERATION", exception.getSQLState()); + } + + @Test + public void testToBooleanWithBooleanTrue() throws DatabricksSQLException { + assertTrue(bitConverter.toBoolean(true)); + } + + @Test + public void testToBooleanWithBooleanFalse() throws DatabricksSQLException { + assertFalse(bitConverter.toBoolean(false)); + } + + @Test + public void testToBooleanWithBooleanObject() throws DatabricksSQLException { + Boolean trueObject = Boolean.TRUE; + Boolean falseObject = Boolean.FALSE; + + assertTrue(bitConverter.toBoolean(trueObject)); + assertFalse(bitConverter.toBoolean(falseObject)); + } + + @ParameterizedTest + @CsvSource({"0, false", "1, true", "-1, true", "42, true", "0.0, false", "3.14, true"}) + public void testToBooleanWithNumbers(String numberStr, boolean expected) + throws DatabricksSQLException { + Number number = + numberStr.contains(".") ? Double.parseDouble(numberStr) : Integer.parseInt(numberStr); + assertEquals(expected, bitConverter.toBoolean(number)); + } + + @ParameterizedTest + @CsvSource({ + "true, true", + "TRUE, true", + "True, true", + "false, false", + "FALSE, false", + "False, false", + "anything else, false", + "'', false", + "1, false", + "0, false" + }) + public void testToBooleanWithStrings(String input, boolean expected) + throws DatabricksSQLException { + assertEquals(expected, bitConverter.toBoolean(input)); + } + + @ParameterizedTest + @CsvSource({ + "null, null", + "Object, Object", + "int[], class [I", + "String[], class [Ljava.lang.String;" + }) + public void testToBooleanWithUnsupportedTypes(String typeDescription, String expectedInMessage) { + Object input = getTestObject(typeDescription); + + DatabricksSQLException exception = + assertThrows(DatabricksSQLException.class, () -> bitConverter.toBoolean(input)); + + assertTrue(exception.getMessage().contains("Unsupported type for conversion to BIT")); + assertTrue(exception.getMessage().contains(expectedInMessage)); + assertEquals("UNSUPPORTED_OPERATION", exception.getSQLState()); + } + + private Object getTestObject(String typeDescription) { + switch (typeDescription) { + case "null": + return null; + case "Object": + return new Object(); + case "int[]": + return new int[] {1, 2, 3}; + case "String[]": + return new String[] {"a", "b"}; + default: + throw new IllegalArgumentException("Unknown type: " + typeDescription); + } + } +}