diff --git a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrow.java b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrow.java index fd320367f77b6..ddf70df9ad2ce 100644 --- a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrow.java +++ b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrow.java @@ -179,13 +179,12 @@ public static VectorSchemaRoot sqlToArrow(ResultSet resultSet, BaseAllocator all * For the given JDBC {@link ResultSet}, fetch the data from Relational DB and convert it to Arrow objects. * * @param resultSet ResultSet to use to fetch the data from underlying database - * @param calendar Calendar instance to use for Date, Time and Timestamp datasets. + * @param calendar Calendar instance to use for Date, Time and Timestamp datasets, or null if none. * @return Arrow Data Objects {@link VectorSchemaRoot} * @throws SQLException on error */ public static VectorSchemaRoot sqlToArrow(ResultSet resultSet, Calendar calendar) throws SQLException, IOException { Preconditions.checkNotNull(resultSet, "JDBC ResultSet object can not be null"); - Preconditions.checkNotNull(calendar, "Calendar object can not be null"); return sqlToArrow(resultSet, new JdbcToArrowConfig(new RootAllocator(Integer.MAX_VALUE), calendar)); } @@ -195,7 +194,7 @@ public static VectorSchemaRoot sqlToArrow(ResultSet resultSet, Calendar calendar * * @param resultSet ResultSet to use to fetch the data from underlying database * @param allocator Memory allocator to use. - * @param calendar Calendar instance to use for Date, Time and Timestamp datasets. + * @param calendar Calendar instance to use for Date, Time and Timestamp datasets, or null if none. * @return Arrow Data Objects {@link VectorSchemaRoot} * @throws SQLException on error */ @@ -203,7 +202,6 @@ public static VectorSchemaRoot sqlToArrow(ResultSet resultSet, BaseAllocator all throws SQLException, IOException { Preconditions.checkNotNull(resultSet, "JDBC ResultSet object can not be null"); Preconditions.checkNotNull(allocator, "Memory Allocator object can not be null"); - Preconditions.checkNotNull(calendar, "Calendar object can not be null"); return sqlToArrow(resultSet, new JdbcToArrowConfig(allocator, calendar)); } diff --git a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfig.java b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfig.java index 59813a830cbed..e9fcffb36b666 100644 --- a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfig.java +++ b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfig.java @@ -48,7 +48,6 @@ public final class JdbcToArrowConfig { */ JdbcToArrowConfig(BaseAllocator allocator, Calendar calendar) { Preconditions.checkNotNull(allocator, "Memory allocator cannot be null"); - Preconditions.checkNotNull(calendar, "Calendar object can not be null"); this.allocator = allocator; this.calendar = calendar; @@ -56,7 +55,8 @@ public final class JdbcToArrowConfig { /** * The calendar to use when defining Arrow Timestamp fields - * and retrieving time-based fields from the database. + * and retrieving {@link Date}, {@link Time}, or {@link Timestamp} + * data types from the {@link ResultSet}, or null if not converting. * @return the calendar. */ public Calendar getCalendar() { diff --git a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigBuilder.java b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigBuilder.java index df97c3a975196..9ba69639905ce 100644 --- a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigBuilder.java +++ b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigBuilder.java @@ -32,7 +32,7 @@ public class JdbcToArrowConfigBuilder { /** * Default constructor for the JdbcToArrowConfigBuilder}. - * Use the setter methods for the allocator and calendar; both must be + * Use the setter methods for the allocator and calendar; the allocator must be * set. Otherwise, {@link #build()} will throw a {@link NullPointerException}. */ public JdbcToArrowConfigBuilder() { @@ -41,9 +41,9 @@ public JdbcToArrowConfigBuilder() { } /** - * Constructor for the JdbcToArrowConfigBuilder. Both the - * allocator and calendar are required. A {@link NullPointerException} - * will be thrown if one of the arguments is null. + * Constructor for the JdbcToArrowConfigBuilder. The + * allocator is required, and a {@link NullPointerException} + * will be thrown if it is null. *

* The allocator is used to construct Arrow vectors from the JDBC ResultSet. * The calendar is used to determine the time zone of {@link java.sql.Timestamp} @@ -59,7 +59,6 @@ public JdbcToArrowConfigBuilder(BaseAllocator allocator, Calendar calendar) { this(); Preconditions.checkNotNull(allocator, "Memory allocator cannot be null"); - Preconditions.checkNotNull(calendar, "Calendar object can not be null"); this.allocator = allocator; this.calendar = calendar; @@ -82,10 +81,8 @@ public JdbcToArrowConfigBuilder setAllocator(BaseAllocator allocator) { * Arrow schema, and reading time-based fields from the JDBC ResultSet. * * @param calendar the calendar to set. - * @exception NullPointerExeption if calendar is null. */ public JdbcToArrowConfigBuilder setCalendar(Calendar calendar) { - Preconditions.checkNotNull(calendar, "Calendar object can not be null"); this.calendar = calendar; return this; } diff --git a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowUtils.java b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowUtils.java index d48cfe2197b0c..b6adbbc7334a4 100644 --- a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowUtils.java +++ b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowUtils.java @@ -240,15 +240,15 @@ private static void allocateVectors(VectorSchemaRoot root, int size) { * * @param rs ResultSet to use to fetch the data from underlying database * @param root Arrow {@link VectorSchemaRoot} object to populate - * @param calendar The calendar to use when reading time-based data. + * @param calendar The calendar to use when reading {@link Date}, {@link Time}, or {@link Timestamp} + * data types from the {@link ResultSet}, or null if not converting. * @throws SQLException on error */ public static void jdbcToArrowVectors(ResultSet rs, VectorSchemaRoot root, Calendar calendar) throws SQLException, IOException { Preconditions.checkNotNull(rs, "JDBC ResultSet object can't be null"); - Preconditions.checkNotNull(root, "Vector Schema cannot be null"); - Preconditions.checkNotNull(calendar, "Calendar object can't be null"); + Preconditions.checkNotNull(root, "JDBC ResultSet object can't be null"); jdbcToArrowVectors(rs, root, new JdbcToArrowConfig(new RootAllocator(0), calendar)); } @@ -274,6 +274,8 @@ public static void jdbcToArrowVectors(ResultSet rs, VectorSchemaRoot root, JdbcT allocateVectors(root, DEFAULT_BUFFER_SIZE); + final Calendar calendar = config.getCalendar(); + int rowCount = 0; while (rs.next()) { for (int i = 1; i <= columnCount; i++) { @@ -324,17 +326,35 @@ public static void jdbcToArrowVectors(ResultSet rs, VectorSchemaRoot root, JdbcT rs.getString(i), !rs.wasNull(), rowCount); break; case Types.DATE: - updateVector((DateMilliVector) root.getVector(columnName), - rs.getDate(i, config.getCalendar()), !rs.wasNull(), rowCount); + final Date date; + if (calendar != null) { + date = rs.getDate(i, calendar); + } else { + date = rs.getDate(i); + } + + updateVector((DateMilliVector) root.getVector(columnName), date, !rs.wasNull(), rowCount); break; case Types.TIME: - updateVector((TimeMilliVector) root.getVector(columnName), - rs.getTime(i, config.getCalendar()), !rs.wasNull(), rowCount); + final Time time; + if (calendar != null) { + time = rs.getTime(i, calendar); + } else { + time = rs.getTime(i); + } + + updateVector((TimeMilliVector) root.getVector(columnName), time, !rs.wasNull(), rowCount); break; case Types.TIMESTAMP: + final Timestamp ts; + if (calendar != null) { + ts = rs.getTimestamp(i, calendar); + } else { + ts = rs.getTimestamp(i); + } + // TODO: Need to handle precision such as milli, micro, nano - updateVector((TimeStampVector) root.getVector(columnName), - rs.getTimestamp(i, config.getCalendar()), !rs.wasNull(), rowCount); + updateVector((TimeStampVector) root.getVector(columnName), ts, !rs.wasNull(), rowCount); break; case Types.BINARY: case Types.VARBINARY: diff --git a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigTest.java b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigTest.java index b4f92fa417026..1d02c888f8537 100644 --- a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigTest.java +++ b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigTest.java @@ -42,14 +42,16 @@ public void testBuilderNullArguments() { new JdbcToArrowConfigBuilder(null, null); } - @Test(expected = NullPointerException.class) public void testConfigNullCalendar() { - new JdbcToArrowConfig(allocator, null); + JdbcToArrowConfig config = new JdbcToArrowConfig(allocator, null); + assertNull(config.getCalendar()); } - @Test(expected = NullPointerException.class) + @Test public void testBuilderNullCalendar() { - new JdbcToArrowConfigBuilder(allocator, null); + JdbcToArrowConfigBuilder builder = new JdbcToArrowConfigBuilder(allocator, null); + JdbcToArrowConfig config = builder.build(); + assertNull(config.getCalendar()); } @Test(expected = NullPointerException.class) @@ -68,10 +70,11 @@ public void testSetNullAllocator() { builder.setAllocator(null); } - @Test(expected = NullPointerException.class) + @Test public void testSetNullCalendar() { JdbcToArrowConfigBuilder builder = new JdbcToArrowConfigBuilder(allocator, calendar); - builder.setCalendar(null); + JdbcToArrowConfig config = builder.setCalendar(null).build(); + assertNull(config.getCalendar()); } @Test