This is an automated email from the ASF dual-hosted git repository.

jbonofre 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 2afc1d30d GH-1311: Use Locale.ROOT when formatting JDBC interval 
strings (#1312)
2afc1d30d is described below

commit 2afc1d30d892467bded7dac8cdfaca009a83ad1e
Author: Abdul Rawoof Khan <[email protected]>
AuthorDate: Sat Oct 3 08:04:45 2026 +0530

    GH-1311: Use Locale.ROOT when formatting JDBC interval strings (#1312)
    
    ## What's Changed
    
    `formatIntervalYear` and `formatIntervalDay` build the Oracle-style
    interval strings the JDBC interval accessor returns from
    `getString()`/`getObject()` with `String.format` and no explicit locale,
    so `java.util.Formatter` renders the `%d` digits using the JVM default
    locale. On a JVM whose default locale uses non-ASCII digits (`ar-EG`,
    `bn-BD`, `mr-IN`, ...) an interval comes back as `+٠٢١-٠٢` instead of
    `+021-02`, which corrupts the value handed to JDBC clients and breaks
    anything parsing it as ASCII. Pass `Locale.ROOT` to both calls, the same
    fix GH-1300 applied to the C Data Interface format strings.
    
    Closes #1311.
---
 .../arrow/driver/jdbc/utils/IntervalStringUtils.java     | 12 ++++++++++--
 .../ArrowFlightJdbcIntervalVectorAccessorTest.java       | 16 ++++++++++++++++
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git 
a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/IntervalStringUtils.java
 
b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/IntervalStringUtils.java
index 1aed6cd2c..20a606971 100644
--- 
a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/IntervalStringUtils.java
+++ 
b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/IntervalStringUtils.java
@@ -18,6 +18,7 @@ package org.apache.arrow.driver.jdbc.utils;
 
 import java.time.Duration;
 import java.time.Period;
+import java.util.Locale;
 import org.apache.arrow.vector.util.DateUtility;
 
 /**
@@ -43,7 +44,7 @@ public final class IntervalStringUtils {
     final int years = (int) (months / DateUtility.yearsToMonths);
     months = months % DateUtility.yearsToMonths;
 
-    return String.format("%c%03d-%02d", neg ? '-' : '+', years, months);
+    return String.format(Locale.ROOT, "%c%03d-%02d", neg ? '-' : '+', years, 
months);
   }
 
   /**
@@ -73,6 +74,13 @@ public final class IntervalStringUtils {
     millis = millis % DateUtility.secondsToMillis;
 
     return String.format(
-        "%c%03d %02d:%02d:%02d.%03d", neg ? '-' : '+', days, hours, minutes, 
seconds, millis);
+        Locale.ROOT,
+        "%c%03d %02d:%02d:%02d.%03d",
+        neg ? '-' : '+',
+        days,
+        hours,
+        minutes,
+        seconds,
+        millis);
   }
 }
diff --git 
a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessorTest.java
 
b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessorTest.java
index 521debc32..457558a04 100644
--- 
a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessorTest.java
+++ 
b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcIntervalVectorAccessorTest.java
@@ -25,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import java.time.Duration;
 import java.time.Period;
 import java.time.format.DateTimeParseException;
+import java.util.Locale;
 import java.util.function.Supplier;
 import java.util.stream.Stream;
 import org.apache.arrow.driver.jdbc.accessor.ArrowFlightJdbcAccessorFactory;
@@ -36,6 +37,7 @@ import org.apache.arrow.vector.IntervalYearVector;
 import org.apache.arrow.vector.PeriodDuration;
 import org.apache.arrow.vector.ValueVector;
 import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
@@ -254,6 +256,20 @@ public class ArrowFlightJdbcIntervalVectorAccessorTest {
     assertEquals("-1567 00:00:00.000", 
formatIntervalDay(Duration.ofDays(-1567)));
   }
 
+  @Test
+  public void testFormatIntervalIgnoresDefaultLocale() {
+    // Locales such as Arabic-Indic render %d with non-ASCII digits; the 
interval strings handed
+    // back through getString() must stay ASCII regardless of the JVM default 
locale.
+    Locale saved = Locale.getDefault();
+    try {
+      Locale.setDefault(Locale.forLanguageTag("ar-EG"));
+      assertEquals("+021-02", formatIntervalYear(Period.of(21, 2, 0)));
+      assertEquals("+001 18:25:16.766", 
formatIntervalDay(Duration.parse("PT42H25M16.766S")));
+    } finally {
+      Locale.setDefault(saved);
+    }
+  }
+
   @ParameterizedTest
   @MethodSource("data")
   public void testShouldGetStringReturnCorrectString(Supplier<ValueVector> 
vectorSupplier)

Reply via email to