From 68343fc44d8e13e4665305d5868dd1cdcfed7d46 Mon Sep 17 00:00:00 2001 From: Madhavendra Rathore Date: Tue, 2 Sep 2025 19:30:22 +0530 Subject: [PATCH 1/4] Added a toString function in BITConverter to fix getString for boolean columns. Fixed toBoolean to handle null. Added tests for both the functions of BITConverter --- .../api/impl/converters/BitConverter.java | 12 +- .../api/impl/converters/BitConverterTest.java | 119 ++++++++++++++++++ 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/databricks/jdbc/api/impl/converters/BitConverterTest.java 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..eab8ffc4b6 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,17 @@ 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(); + } + // For other types, fall back to the default behavior + throw new DatabricksSQLException( + "Unsupported String conversion operation", 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..504905a0ce --- /dev/null +++ b/src/test/java/com/databricks/jdbc/api/impl/converters/BitConverterTest.java @@ -0,0 +1,119 @@ +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; + +public class BitConverterTest { + + private final BitConverter bitConverter = new BitConverter(); + + @Test + public void testToStringWithBooleanTrue() throws DatabricksSQLException { + assertEquals("true", bitConverter.toString(true)); + } + + @Test + public void testToStringWithBooleanFalse() throws DatabricksSQLException { + assertEquals("false", bitConverter.toString(false)); + } + + @Test + public void testToStringWithBooleanObject() throws DatabricksSQLException { + Boolean trueObject = Boolean.TRUE; + Boolean falseObject = Boolean.FALSE; + + assertEquals("true", bitConverter.toString(trueObject)); + assertEquals("false", bitConverter.toString(falseObject)); + } + + @Test + public void testToStringWithUnsupportedType() { + DatabricksSQLException exception = + assertThrows(DatabricksSQLException.class, () -> bitConverter.toString("not a boolean")); + + assertTrue(exception.getMessage().contains("Unsupported String conversion operation")); + assertEquals("UNSUPPORTED_OPERATION", exception.getSQLState()); + } + + @Test + public void testToStringWithNumber() { + DatabricksSQLException exception = + assertThrows(DatabricksSQLException.class, () -> bitConverter.toString(123)); + + assertTrue(exception.getMessage().contains("Unsupported String conversion operation")); + 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)); + } + + @Test + public void testToBooleanWithNumberZero() throws DatabricksSQLException { + assertFalse(bitConverter.toBoolean(0)); + assertFalse(bitConverter.toBoolean(0L)); + assertFalse(bitConverter.toBoolean(0.0f)); + assertFalse(bitConverter.toBoolean(0.0)); + } + + @Test + public void testToBooleanWithNumberNonZero() throws DatabricksSQLException { + assertTrue(bitConverter.toBoolean(1)); + assertTrue(bitConverter.toBoolean(-1)); + assertTrue(bitConverter.toBoolean(42L)); + assertTrue(bitConverter.toBoolean(3.14f)); + assertTrue(bitConverter.toBoolean(2.71)); + } + + @Test + public void testToBooleanWithStringTrue() throws DatabricksSQLException { + assertTrue(bitConverter.toBoolean("true")); + assertTrue(bitConverter.toBoolean("TRUE")); + assertTrue(bitConverter.toBoolean("True")); + } + + @Test + public void testToBooleanWithStringFalse() throws DatabricksSQLException { + assertFalse(bitConverter.toBoolean("false")); + assertFalse(bitConverter.toBoolean("FALSE")); + assertFalse(bitConverter.toBoolean("False")); + assertFalse(bitConverter.toBoolean("anything else")); + } + + @Test + public void testToBooleanWithUnsupportedType() { + DatabricksSQLException exception = + assertThrows(DatabricksSQLException.class, () -> bitConverter.toBoolean(new Object())); + + assertTrue(exception.getMessage().contains("Unsupported type for conversion to BIT")); + assertTrue(exception.getMessage().contains("Object")); + assertEquals("UNSUPPORTED_OPERATION", exception.getSQLState()); + } + + @Test + public void testToBooleanWithNull() { + DatabricksSQLException exception = + assertThrows(DatabricksSQLException.class, () -> bitConverter.toBoolean(null)); + + assertTrue(exception.getMessage().contains("Unsupported type for conversion to BIT")); + assertTrue(exception.getMessage().contains("null")); + assertEquals("UNSUPPORTED_OPERATION", exception.getSQLState()); + } +} From c23b341421e42820fbbb84e0546681cf8b0ef3a1 Mon Sep 17 00:00:00 2001 From: Madhavendra Rathore Date: Tue, 2 Sep 2025 22:10:05 +0530 Subject: [PATCH 2/4] Added parameterised tests for BITConverter --- .../api/impl/converters/BitConverterTest.java | 131 +++++++++--------- 1 file changed, 65 insertions(+), 66 deletions(-) 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 index 504905a0ce..04b40a6bce 100644 --- a/src/test/java/com/databricks/jdbc/api/impl/converters/BitConverterTest.java +++ b/src/test/java/com/databricks/jdbc/api/impl/converters/BitConverterTest.java @@ -4,43 +4,34 @@ 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(); - @Test - public void testToStringWithBooleanTrue() throws DatabricksSQLException { - assertEquals("true", bitConverter.toString(true)); - } - - @Test - public void testToStringWithBooleanFalse() throws DatabricksSQLException { - assertEquals("false", bitConverter.toString(false)); + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void testToStringWithBooleanPrimitives(boolean input) throws DatabricksSQLException { + String expected = input ? "true" : "false"; + assertEquals(expected, bitConverter.toString(input)); } - @Test - public void testToStringWithBooleanObject() throws DatabricksSQLException { - Boolean trueObject = Boolean.TRUE; - Boolean falseObject = Boolean.FALSE; - - assertEquals("true", bitConverter.toString(trueObject)); - assertEquals("false", bitConverter.toString(falseObject)); + @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)); } - @Test - public void testToStringWithUnsupportedType() { + @ParameterizedTest + @ValueSource(strings = {"not a boolean", "123", "test"}) + public void testToStringWithUnsupportedStringTypes(String input) { DatabricksSQLException exception = - assertThrows(DatabricksSQLException.class, () -> bitConverter.toString("not a boolean")); - - assertTrue(exception.getMessage().contains("Unsupported String conversion operation")); - assertEquals("UNSUPPORTED_OPERATION", exception.getSQLState()); - } - - @Test - public void testToStringWithNumber() { - DatabricksSQLException exception = - assertThrows(DatabricksSQLException.class, () -> bitConverter.toString(123)); + assertThrows(DatabricksSQLException.class, () -> bitConverter.toString(input)); assertTrue(exception.getMessage().contains("Unsupported String conversion operation")); assertEquals("UNSUPPORTED_OPERATION", exception.getSQLState()); @@ -65,55 +56,63 @@ public void testToBooleanWithBooleanObject() throws DatabricksSQLException { assertFalse(bitConverter.toBoolean(falseObject)); } - @Test - public void testToBooleanWithNumberZero() throws DatabricksSQLException { - assertFalse(bitConverter.toBoolean(0)); - assertFalse(bitConverter.toBoolean(0L)); - assertFalse(bitConverter.toBoolean(0.0f)); - assertFalse(bitConverter.toBoolean(0.0)); + @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)); } - @Test - public void testToBooleanWithNumberNonZero() throws DatabricksSQLException { - assertTrue(bitConverter.toBoolean(1)); - assertTrue(bitConverter.toBoolean(-1)); - assertTrue(bitConverter.toBoolean(42L)); - assertTrue(bitConverter.toBoolean(3.14f)); - assertTrue(bitConverter.toBoolean(2.71)); + @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)); } - @Test - public void testToBooleanWithStringTrue() throws DatabricksSQLException { - assertTrue(bitConverter.toBoolean("true")); - assertTrue(bitConverter.toBoolean("TRUE")); - assertTrue(bitConverter.toBoolean("True")); - } - - @Test - public void testToBooleanWithStringFalse() throws DatabricksSQLException { - assertFalse(bitConverter.toBoolean("false")); - assertFalse(bitConverter.toBoolean("FALSE")); - assertFalse(bitConverter.toBoolean("False")); - assertFalse(bitConverter.toBoolean("anything else")); - } + @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); - @Test - public void testToBooleanWithUnsupportedType() { DatabricksSQLException exception = - assertThrows(DatabricksSQLException.class, () -> bitConverter.toBoolean(new Object())); + assertThrows(DatabricksSQLException.class, () -> bitConverter.toBoolean(input)); assertTrue(exception.getMessage().contains("Unsupported type for conversion to BIT")); - assertTrue(exception.getMessage().contains("Object")); + assertTrue(exception.getMessage().contains(expectedInMessage)); assertEquals("UNSUPPORTED_OPERATION", exception.getSQLState()); } - @Test - public void testToBooleanWithNull() { - DatabricksSQLException exception = - assertThrows(DatabricksSQLException.class, () -> bitConverter.toBoolean(null)); - - assertTrue(exception.getMessage().contains("Unsupported type for conversion to BIT")); - assertTrue(exception.getMessage().contains("null")); - 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); + } } } From 7a0d67881855b57aac3c555a1d4a4ad57aa3bac8 Mon Sep 17 00:00:00 2001 From: Madhavendra Rathore Date: Tue, 2 Sep 2025 22:44:12 +0530 Subject: [PATCH 3/4] Updated the exception message --- .../jdbc/api/impl/converters/BitConverter.java | 5 +++-- .../jdbc/api/impl/converters/BitConverterTest.java | 14 +++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) 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 eab8ffc4b6..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 @@ -26,8 +26,9 @@ public String toString(Object object) throws DatabricksSQLException { if (object instanceof Boolean) { return object.toString(); } - // For other types, fall back to the default behavior throw new DatabricksSQLException( - "Unsupported String conversion operation", DatabricksDriverErrorCode.UNSUPPORTED_OPERATION); + "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 index 04b40a6bce..4245da9030 100644 --- a/src/test/java/com/databricks/jdbc/api/impl/converters/BitConverterTest.java +++ b/src/test/java/com/databricks/jdbc/api/impl/converters/BitConverterTest.java @@ -28,12 +28,20 @@ public void testToStringWithBooleanObjects(String input, String expected) } @ParameterizedTest - @ValueSource(strings = {"not a boolean", "123", "test"}) - public void testToStringWithUnsupportedStringTypes(String input) { + @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 String conversion operation")); + assertTrue(exception.getMessage().contains("Unsupported type for conversion to String")); + assertTrue(exception.getMessage().contains(expectedInMessage)); assertEquals("UNSUPPORTED_OPERATION", exception.getSQLState()); } From ed0dcc8125cac51f499f48e00df0fdb8037d29e7 Mon Sep 17 00:00:00 2001 From: Madhavendra Rathore Date: Wed, 3 Sep 2025 15:02:45 +0530 Subject: [PATCH 4/4] Updated NEXT_CHANGELOG --- NEXT_CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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.*