This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-java.git
The following commit(s) were added to refs/heads/main by this push:
new ec6eb6750 GH-477: Fix Flight JDBC DATE(MILLISECOND) parameter binding
(#1219)
ec6eb6750 is described below
commit ec6eb67500223f951448c113c2dad4b32855ca17
Author: yujin5701 <[email protected]>
AuthorDate: Thu Aug 27 11:44:27 2026 +0900
GH-477: Fix Flight JDBC DATE(MILLISECOND) parameter binding (#1219)
## What's Changed
This fixes Flight JDBC prepared statement binding for Arrow
`DATE(MILLISECOND)` parameters.
Avatica represents JDBC `DATE` values as days since the Unix
epoch. The Flight JDBC parameter binder already writes that
value correctly for `DateDayVector`, but it was also writing
the same day value directly into `DateMilliVector`, which
expects milliseconds since the Unix epoch.
This now converts epoch days to epoch milliseconds before
writing to `DateMilliVector`.
Tested with `ArrowFlightPreparedStatementTest`.
Closes #477.
---
.../impl/DateAvaticaParameterConverter.java | 3 +-
.../jdbc/ArrowFlightPreparedStatementTest.java | 46 ++++++++++++++++++++++
2 files changed, 48 insertions(+), 1 deletion(-)
diff --git
a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/converter/impl/DateAvaticaParameterConverter.java
b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/converter/impl/DateAvaticaParameterConverter.java
index 879521353..ebbfae6fb 100644
---
a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/converter/impl/DateAvaticaParameterConverter.java
+++
b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/converter/impl/DateAvaticaParameterConverter.java
@@ -16,6 +16,7 @@
*/
package org.apache.arrow.driver.jdbc.converter.impl;
+import java.util.concurrent.TimeUnit;
import org.apache.arrow.vector.DateDayVector;
import org.apache.arrow.vector.DateMilliVector;
import org.apache.arrow.vector.FieldVector;
@@ -33,7 +34,7 @@ public class DateAvaticaParameterConverter extends
BaseAvaticaParameterConverter
public boolean bindParameter(FieldVector vector, TypedValue typedValue, int
index) {
int value = (int) typedValue.toLocal();
if (vector instanceof DateMilliVector) {
- ((DateMilliVector) vector).setSafe(index, value);
+ ((DateMilliVector) vector).setSafe(index, TimeUnit.DAYS.toMillis(value));
return true;
} else if (vector instanceof DateDayVector) {
((DateDayVector) vector).setSafe(index, value);
diff --git
a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowFlightPreparedStatementTest.java
b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowFlightPreparedStatementTest.java
index 078837adf..73ece4640 100644
---
a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowFlightPreparedStatementTest.java
+++
b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowFlightPreparedStatementTest.java
@@ -25,9 +25,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
+import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.time.LocalDate;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -38,6 +40,7 @@ import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.memory.RootAllocator;
import org.apache.arrow.vector.IntVector;
import org.apache.arrow.vector.VectorSchemaRoot;
+import org.apache.arrow.vector.types.DateUnit;
import org.apache.arrow.vector.types.Types;
import org.apache.arrow.vector.types.pojo.ArrowType;
import org.apache.arrow.vector.types.pojo.Field;
@@ -180,6 +183,49 @@ public class ArrowFlightPreparedStatementTest {
}
}
+ @Test
+ public void testQueryWithDateMillisecondParameterBinding() throws
SQLException {
+ final String query = "Fake query with date millisecond parameter";
+ final Schema schema =
+ new Schema(Collections.singletonList(Field.nullable("",
Types.MinorType.INT.getType())));
+ final Schema parameterSchema =
+ new Schema(
+ Collections.singletonList(
+ Field.nullable("", new ArrowType.Date(DateUnit.MILLISECOND))));
+ final LocalDate date = LocalDate.of(2000, 1, 1);
+ final List<List<Object>> expected =
+
Collections.singletonList(Collections.singletonList(date.atStartOfDay()));
+
+ PRODUCER.addSelectQuery(
+ query,
+ schema,
+ Collections.singletonList(
+ listener -> {
+ try (final BufferAllocator allocator = new
RootAllocator(Long.MAX_VALUE);
+ final VectorSchemaRoot root =
VectorSchemaRoot.create(schema, allocator)) {
+ ((IntVector) root.getVector(0)).setSafe(0, 10);
+ root.setRowCount(1);
+ listener.start(root);
+ listener.putNext();
+ } catch (final Throwable throwable) {
+ listener.error(throwable);
+ } finally {
+ listener.completed();
+ }
+ }));
+
+ PRODUCER.addExpectedParameters(query, parameterSchema, expected);
+
+ try (final PreparedStatement preparedStatement =
connection.prepareStatement(query)) {
+ preparedStatement.setDate(1, Date.valueOf(date));
+
+ try (final ResultSet resultSet = preparedStatement.executeQuery()) {
+ resultSet.next();
+ assert true;
+ }
+ }
+ }
+
@Test
@Disabled("https://github.com/apache/arrow/issues/34741: flaky test")
public void testPreparedStatementExecutionOnce() throws SQLException {