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 {

Reply via email to