diff --git a/c/src/main/java/org/apache/arrow/c/Format.java b/c/src/main/java/org/apache/arrow/c/Format.java index 7ce99614d2..7f546fca2c 100644 --- a/c/src/main/java/org/apache/arrow/c/Format.java +++ b/c/src/main/java/org/apache/arrow/c/Format.java @@ -63,10 +63,10 @@ static String asString(ArrowType arrowType) { { ArrowType.Decimal type = (ArrowType.Decimal) arrowType; if (type.getBitWidth() == 128) { - return String.format("d:%d,%d", type.getPrecision(), type.getScale()); + return String.format(Locale.ROOT, "d:%d,%d", type.getPrecision(), type.getScale()); } return String.format( - "d:%d,%d,%d", type.getPrecision(), type.getScale(), type.getBitWidth()); + Locale.ROOT, "d:%d,%d,%d", type.getPrecision(), type.getScale(), type.getBitWidth()); } case Duration: { @@ -88,12 +88,12 @@ static String asString(ArrowType arrowType) { case FixedSizeBinary: { ArrowType.FixedSizeBinary type = (ArrowType.FixedSizeBinary) arrowType; - return String.format("w:%d", type.getByteWidth()); + return String.format(Locale.ROOT, "w:%d", type.getByteWidth()); } case FixedSizeList: { ArrowType.FixedSizeList type = (ArrowType.FixedSizeList) arrowType; - return String.format("+w:%d", type.getListSize()); + return String.format(Locale.ROOT, "+w:%d", type.getListSize()); } case FloatingPoint: { diff --git a/c/src/test/java/org/apache/arrow/c/FormatTest.java b/c/src/test/java/org/apache/arrow/c/FormatTest.java index c773324330..3691ca095d 100644 --- a/c/src/test/java/org/apache/arrow/c/FormatTest.java +++ b/c/src/test/java/org/apache/arrow/c/FormatTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.Locale; import org.apache.arrow.vector.types.DateUnit; import org.apache.arrow.vector.types.FloatingPointPrecision; import org.apache.arrow.vector.types.IntervalUnit; @@ -156,4 +157,20 @@ public void testAsType() assertThrows(UnsupportedOperationException.class, () -> Format.asType(":", 0L)); assertThrows(NumberFormatException.class, () -> Format.asType("w:1,2,3", 0L)); } + + @Test + public void testAsStringIgnoresDefaultLocale() { + // Locales that use digits other than 0-9 (Arabic-Indic, Bengali, Devanagari, ...) + // must not leak into the format string, which other implementations parse as ASCII. + Locale saved = Locale.getDefault(); + try { + Locale.setDefault(Locale.forLanguageTag("ar-EG")); + assertEquals("d:10,2", Format.asString(new ArrowType.Decimal(10, 2, 128))); + assertEquals("d:10,2,256", Format.asString(new ArrowType.Decimal(10, 2, 256))); + assertEquals("w:16", Format.asString(new ArrowType.FixedSizeBinary(16))); + assertEquals("+w:8", Format.asString(new ArrowType.FixedSizeList(8))); + } finally { + Locale.setDefault(saved); + } + } }