diff --git a/src/integrationTest/java/org/itsallcode/jdbc/ExasolTypeTest.java b/src/integrationTest/java/org/itsallcode/jdbc/ExasolTypeTest.java index 563648a..8473b1e 100644 --- a/src/integrationTest/java/org/itsallcode/jdbc/ExasolTypeTest.java +++ b/src/integrationTest/java/org/itsallcode/jdbc/ExasolTypeTest.java @@ -4,11 +4,13 @@ import static org.junit.jupiter.api.Assertions.assertAll; import java.math.BigDecimal; +import java.sql.JDBCType; import java.time.Instant; import java.time.LocalDate; import java.util.stream.Stream; import org.itsallcode.jdbc.resultset.SimpleResultSet; +import org.itsallcode.jdbc.resultset.generic.ColumnValue; import org.itsallcode.jdbc.resultset.generic.Row; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -44,10 +46,12 @@ SimpleConnection connect() { void genericRowType(final TypeTest test) { try (SimpleResultSet result = connect() .query("select cast('" + test.value() + "' as " + test.type() + ")")) { - final Object value = result.toList().get(0).get(0).value(); + final ColumnValue columnValue = result.toList().get(0).get(0); + final Object value = columnValue.value(); assertAll( () -> assertThat(value.getClass()).isEqualTo(test.expectedValue().getClass()), - () -> assertThat(value).isEqualTo(test.expectedValue())); + () -> assertThat(value).isEqualTo(test.expectedValue()), + () -> assertThat(columnValue.type().jdbcType()).isEqualTo(test.expectedType())); } } @@ -56,8 +60,10 @@ void genericRowType(final TypeTest test) { void genericRowNullValue(final TypeTest test) { try (SimpleResultSet result = connect() .query("select cast(NULL as " + test.type() + ")")) { - assertThat(result.toList().get(0).get(0).value()) - .isNull(); + final ColumnValue value = result.toList().get(0).get(0); + assertAll( + () -> assertThat(value.value()).isNull(), + () -> assertThat(value.type().jdbcType()).isEqualTo(test.expectedType())); } } @@ -78,25 +84,45 @@ void resultSetValueTypes(final TypeTest test) { static Stream testTypes() { return Stream.of( - typeTest("2023-11-25 16:18:46", "timestamp", Instant.parse("2023-11-25T16:18:46.0Z")), - typeTest("2023-11-25", "date", LocalDate.parse("2023-11-25")), - typeTest("5-3", "INTERVAL YEAR TO MONTH", "+05-03"), - typeTest("2 12:50:10.123", "INTERVAL DAY TO SECOND", "+02 12:50:10.123"), - typeTest("POINT(1 2)", "GEOMETRY", "POINT (1 2)"), - typeTest("550e8400-e29b-11d4-a716-446655440000", "HASHTYPE", "550e8400e29b11d4a716446655440000"), - typeTest("text", "VARCHAR(10)", "text"), - typeTest("text", "CHAR(10)", "text "), - typeTest("123.456", "DECIMAL", 123L), - typeTest("123.457", "DECIMAL(6,3)", BigDecimal.valueOf(123.457d)), - typeTest("123.458", "DOUBLE PRECISION", 123.458d), - typeTest("true", "BOOLEAN", true)); + typeTest("2023-11-25 16:18:46", "timestamp", Instant.parse("2023-11-25T16:18:46.0Z"), + JDBCType.TIMESTAMP), + typeTest("2023-11-25", "date", LocalDate.parse("2023-11-25"), JDBCType.DATE), + typeTest("5-3", "INTERVAL YEAR TO MONTH", "+05-03", JDBCType.VARCHAR), + typeTest("2 12:50:10.123", "INTERVAL DAY TO SECOND", "+02 12:50:10.123", JDBCType.VARCHAR), + typeTest("POINT(1 2)", "GEOMETRY", "POINT (1 2)", JDBCType.VARCHAR), + typeTest("550e8400-e29b-11d4-a716-446655440000", "HASHTYPE", "550e8400e29b11d4a716446655440000", + JDBCType.CHAR), + typeTest("text", "VARCHAR(10)", "text", JDBCType.VARCHAR), + typeTest("text", "CHAR(10)", "text ", JDBCType.CHAR), + typeTest("123.456", "DECIMAL", 123L, JDBCType.BIGINT), + typeTest("123", "SHORTINT", 123, JDBCType.INTEGER), + typeTest("123", "SMALLINT", 123, JDBCType.INTEGER), + typeTest("123", "TINYINT", (short) 123, JDBCType.SMALLINT), + typeTest("123", "DECIMAL(4,0)", (short) 123, JDBCType.SMALLINT), + typeTest("123", "DECIMAL(5,0)", 123, JDBCType.INTEGER), + typeTest("123", "DECIMAL(9,0)", 123, JDBCType.INTEGER), + typeTest("123", "DECIMAL(10,0)", 123L, JDBCType.BIGINT), + typeTest("123", "DECIMAL(18,0)", 123L, JDBCType.BIGINT), + typeTest("123", "DECIMAL(19,0)", BigDecimal.valueOf(123), JDBCType.DECIMAL), + typeTest("123", "INT", 123L, JDBCType.BIGINT), + typeTest("123", "BIGINT", BigDecimal.valueOf(123), JDBCType.DECIMAL), + typeTest("123", "DEC", 123L, JDBCType.BIGINT), + typeTest("123", "NUMERIC", 123L, JDBCType.BIGINT), + typeTest("123.457", "DECIMAL(6,3)", BigDecimal.valueOf(123.457d), JDBCType.DECIMAL), + typeTest("123.458", "DOUBLE", 123.458d, JDBCType.DOUBLE), + typeTest("123.458", "FLOAT", 123.458d, JDBCType.DOUBLE), + typeTest("123.458", "NUMBER", 123.458d, JDBCType.DOUBLE), + typeTest("123.458", "REAL", 123.458d, JDBCType.DOUBLE), + typeTest("123.458", "DOUBLE PRECISION", 123.458d, JDBCType.DOUBLE), + typeTest("true", "BOOLEAN", true, JDBCType.BOOLEAN)); } - private static Arguments typeTest(final String value, final String type, final Object expectedValue) { - return Arguments.of(new TypeTest(value, type, expectedValue)); + private static Arguments typeTest(final String value, final String type, final Object expectedValue, + final JDBCType expectedType) { + return Arguments.of(new TypeTest(value, type, expectedValue, expectedType)); } - record TypeTest(String value, String type, Object expectedValue) { + record TypeTest(String value, String type, Object expectedValue, JDBCType expectedType) { } } diff --git a/src/main/java/org/itsallcode/jdbc/resultset/generic/ColumnType.java b/src/main/java/org/itsallcode/jdbc/resultset/generic/ColumnType.java index e592420..c234c1c 100644 --- a/src/main/java/org/itsallcode/jdbc/resultset/generic/ColumnType.java +++ b/src/main/java/org/itsallcode/jdbc/resultset/generic/ColumnType.java @@ -1,7 +1,6 @@ package org.itsallcode.jdbc.resultset.generic; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; +import java.sql.*; /** * Represents the type of a column. @@ -14,13 +13,13 @@ * @param scale column scale * @param displaySize display size */ -public record ColumnType(JdbcType jdbcType, String typeName, String className, int precision, int scale, +public record ColumnType(JDBCType jdbcType, String typeName, String className, int precision, int scale, int displaySize) { static ColumnType create(final ResultSetMetaData metaData, final int columnIndex) throws SQLException { final String className = metaData.getColumnClassName(columnIndex); final int displaySize = metaData.getColumnDisplaySize(columnIndex); - final JdbcType jdbcType = JdbcType.forType(metaData.getColumnType(columnIndex)); + final JDBCType jdbcType = JDBCType.valueOf(metaData.getColumnType(columnIndex)); final String typeName = metaData.getColumnTypeName(columnIndex); final int precision = metaData.getPrecision(columnIndex); final int scale = metaData.getScale(columnIndex); diff --git a/src/main/java/org/itsallcode/jdbc/resultset/generic/JdbcType.java b/src/main/java/org/itsallcode/jdbc/resultset/generic/JdbcType.java deleted file mode 100644 index 75f7986..0000000 --- a/src/main/java/org/itsallcode/jdbc/resultset/generic/JdbcType.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.itsallcode.jdbc.resultset.generic; - -import java.sql.Types; -import java.util.Arrays; - -/** - * Enum for values in {@link Types}. - */ -public enum JdbcType { - /** SQL type {@code BIT} */ - BIT(Types.BIT), - /** SQL type {@code TINYINT} */ - TINYINT(Types.TINYINT), - /** SQL type {@code SMALLINT} */ - SMALLINT(Types.SMALLINT), - /** SQL type {@code INTEGER} */ - INTEGER(Types.INTEGER), - /** SQL type {@code BIGINT} */ - BIGINT(Types.BIGINT), - /** SQL type {@code FLOAT} */ - FLOAT(Types.FLOAT), - /** SQL type {@code REAL} */ - REAL(Types.REAL), - /** SQL type {@code DOUBLE} */ - DOUBLE(Types.DOUBLE), - /** SQL type {@code NUMERIC} */ - NUMERIC(Types.NUMERIC), - /** SQL type {@code DECIMAL} */ - DECIMAL(Types.DECIMAL), - /** SQL type {@code CHAR} */ - CHAR(Types.CHAR), - /** SQL type {@code VARCHAR} */ - VARCHAR(Types.VARCHAR), - /** SQL type {@code LONGVARCHAR} */ - LONGVARCHAR(Types.LONGVARCHAR), - /** SQL type {@code DATE} */ - DATE(Types.DATE), - /** SQL type {@code TIME} */ - TIME(Types.TIME), - /** SQL type {@code TIMESTAMP} */ - TIMESTAMP(Types.TIMESTAMP), - /** SQL type {@code BINARY} */ - BINARY(Types.BINARY), - /** SQL type {@code VARBINARY} */ - VARBINARY(Types.VARBINARY), - /** SQL type {@code LONGVARBINARY} */ - LONGVARBINARY(Types.LONGVARBINARY), - /** SQL type {@code NULL} */ - NULL(Types.NULL), - /** Database specific type */ - OTHER(Types.OTHER), - /** SQL type {@code JAVA_OBJECT} */ - JAVA_OBJECT(Types.JAVA_OBJECT), - /** SQL type {@code DISTINCT} */ - DISTINCT(Types.DISTINCT), - /** SQL type {@code STRUCT} */ - STRUCT(Types.STRUCT), - /** SQL type {@code ARRAY} */ - ARRAY(Types.ARRAY), - /** SQL type {@code BLOB} */ - BLOB(Types.BLOB), - /** SQL type {@code CLOB} */ - CLOB(Types.CLOB), - /** SQL type {@code REF} */ - REF(Types.REF), - /** SQL type {@code DATALINK} */ - DATALINK(Types.DATALINK), - /** SQL type {@code BOOLEAN} */ - BOOLEAN(Types.BOOLEAN), - /** SQL type {@code ROWID} */ - ROWID(Types.ROWID), - /** SQL type {@code NCHAR} */ - NCHAR(Types.NCHAR), - /** SQL type {@code NVARCHAR} */ - NVARCHAR(Types.NVARCHAR), - /** SQL type {@code LONGNVARCHAR} */ - LONGNVARCHAR(Types.LONGNVARCHAR), - /** SQL type {@code NCLOB} */ - NCLOB(Types.NCLOB), - /** SQL type {@code XML} */ - SQLXML(Types.SQLXML), - /** SQL type {@code REF CURSOR} */ - REF_CURSOR(Types.REF_CURSOR), - /** SQL type {@code TIME WITH TIMEZONE} */ - TIME_WITH_TIMEZONE(Types.TIME_WITH_TIMEZONE), - /** SQL type {@code TIMESTAMP WITH TIMEZONE} */ - TIMESTAMP_WITH_TIMEZONE(Types.TIMESTAMP_WITH_TIMEZONE); - - private final int type; - - private JdbcType(final int type) { - this.type = type; - } - - /** - * Get the {@link JdbcType} for the given value from {@link Types}. - * - * @param type the type to convert - * @return {@link JdbcType} value - */ - public static JdbcType forType(final int type) { - return Arrays.stream(values()) - .filter(t -> t.type == type).findFirst() - .orElseThrow(() -> new IllegalArgumentException("No JDBC type found for value " + type)); - } -} diff --git a/src/test/java/org/itsallcode/jdbc/SimpleConnectionITest.java b/src/test/java/org/itsallcode/jdbc/SimpleConnectionITest.java index 72ea01e..5360bd5 100644 --- a/src/test/java/org/itsallcode/jdbc/SimpleConnectionITest.java +++ b/src/test/java/org/itsallcode/jdbc/SimpleConnectionITest.java @@ -6,6 +6,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import java.sql.JDBCType; import java.sql.SQLException; import java.util.*; import java.util.stream.Stream; @@ -13,7 +14,6 @@ import org.itsallcode.jdbc.identifier.Identifier; import org.itsallcode.jdbc.resultset.ContextRowMapper; import org.itsallcode.jdbc.resultset.SimpleResultSet; -import org.itsallcode.jdbc.resultset.generic.JdbcType; import org.itsallcode.jdbc.resultset.generic.Row; import org.junit.jupiter.api.Test; @@ -101,7 +101,7 @@ void executeQuerySingleRow() { () -> assertThat(firstRow.columnValues()).hasSize(2), () -> assertThat(firstRow.columnValues().get(0).value()).isEqualTo(1), () -> assertThat(firstRow.columnValues().get(0).type().jdbcType()) - .isEqualTo(JdbcType.INTEGER), + .isEqualTo(JDBCType.INTEGER), () -> assertThat(firstRow.columnValues().get(0).type().typeName()) .isEqualTo("INTEGER"), () -> assertThat(firstRow.columnValues().get(0).type().className()) @@ -112,7 +112,7 @@ void executeQuerySingleRow() { () -> assertThat(firstRow.columnValues().get(1).value()).isEqualTo("test"), () -> assertThat(firstRow.columnValues().get(1).type().jdbcType()) - .isEqualTo(JdbcType.VARCHAR), + .isEqualTo(JDBCType.VARCHAR), () -> assertThat(firstRow.columnValues().get(1).type().typeName()) .isEqualTo("CHARACTER VARYING"), () -> assertThat(firstRow.columnValues().get(1).type().className()) diff --git a/src/test/java/org/itsallcode/jdbc/resultset/generic/JdbcTypeTest.java b/src/test/java/org/itsallcode/jdbc/resultset/generic/JdbcTypeTest.java index ac9bb42..b8fa2c4 100644 --- a/src/test/java/org/itsallcode/jdbc/resultset/generic/JdbcTypeTest.java +++ b/src/test/java/org/itsallcode/jdbc/resultset/generic/JdbcTypeTest.java @@ -3,20 +3,21 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import java.sql.JDBCType; import java.sql.Types; import org.junit.jupiter.api.Test; -class JdbcTypeTest { +class JDBCTypeTest { @Test void typeFound() { - assertThat(JdbcType.forType(Types.VARCHAR)).isEqualTo(JdbcType.VARCHAR); + assertThat(JDBCType.valueOf(Types.VARCHAR)).isEqualTo(JDBCType.VARCHAR); } @Test void typeNotFound() { - assertThatThrownBy(() -> JdbcType.forType(Integer.MIN_VALUE)) + assertThatThrownBy(() -> JDBCType.valueOf(Integer.MIN_VALUE)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("No JDBC type found for value -2147483648"); + .hasMessageContaining("Type:-2147483648 is not a valid Types.java value."); } }