diff --git a/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java b/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java index ed10468095b88..c5fef82d05276 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java @@ -20,6 +20,7 @@ import static org.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED; import java.math.BigDecimal; +import java.nio.ByteOrder; import org.apache.arrow.memory.ArrowBuf; import org.apache.arrow.memory.BufferAllocator; @@ -43,6 +44,7 @@ */ public final class Decimal256Vector extends BaseFixedWidthVector { public static final byte TYPE_WIDTH = 32; + private static final boolean LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN; private final FieldReader reader; private final int precision; @@ -197,7 +199,7 @@ public void set(int index, ArrowBuf buffer) { /** * Set the decimal element at given index to the provided array of bytes. - * Decimal256 is now implemented as Little Endian. This API allows the user + * Decimal256 is now implemented as Native Endian. This API allows the user * to pass a decimal value in the form of byte array in BE byte order. * *
Consumers of Arrow code can use this API instead of first swapping @@ -218,25 +220,38 @@ public void setBigEndian(int index, byte[] value) { valueBuffer.checkBytes((long) index * TYPE_WIDTH, (long) (index + 1) * TYPE_WIDTH); long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH; - // swap bytes to convert BE to LE - for (int byteIdx = 0; byteIdx < length; ++byteIdx) { - PlatformDependent.putByte(outAddress + byteIdx, value[length - 1 - byteIdx]); - } - - if (length == TYPE_WIDTH) { - return; - } - if (length == 0) { PlatformDependent.setMemory(outAddress, Decimal256Vector.TYPE_WIDTH, (byte) 0); - } else if (length < TYPE_WIDTH) { - // sign extend - final byte pad = (byte) (value[0] < 0 ? 0xFF : 0x00); - PlatformDependent.setMemory(outAddress + length, Decimal256Vector.TYPE_WIDTH - length, pad); + return; + } + if (LITTLE_ENDIAN) { + // swap bytes to convert BE to LE + for (int byteIdx = 0; byteIdx < length; ++byteIdx) { + PlatformDependent.putByte(outAddress + byteIdx, value[length - 1 - byteIdx]); + } + + if (length == TYPE_WIDTH) { + return; + } + + if (length < TYPE_WIDTH) { + // sign extend + final byte pad = (byte) (value[0] < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress + length, Decimal256Vector.TYPE_WIDTH - length, pad); + return; + } } else { - throw new IllegalArgumentException( - "Invalid decimal value length. Valid length in [1 - 32], got " + length); + if (length <= TYPE_WIDTH) { + // copy data from value to outAddress + PlatformDependent.copyMemory(value, 0, outAddress + Decimal256Vector.TYPE_WIDTH - length, length); + // sign extend + final byte pad = (byte) (value[0] < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress, Decimal256Vector.TYPE_WIDTH - length, pad); + return; + } } + throw new IllegalArgumentException( + "Invalid decimal value length. Valid length in [1 - 32], got " + length); } /** @@ -255,7 +270,7 @@ public void set(int index, long start, ArrowBuf buffer) { * Sets the element at given index using the buffer whose size maybe <= 32 bytes. * @param index index to write the decimal to * @param start start of value in the buffer - * @param buffer contains the decimal in little endian bytes + * @param buffer contains the decimal in native endian bytes * @param length length of the value in the buffer */ public void setSafe(int index, long start, ArrowBuf buffer, int length) { @@ -268,12 +283,22 @@ public void setSafe(int index, long start, ArrowBuf buffer, int length) { long inAddress = buffer.memoryAddress() + start; long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH; - PlatformDependent.copyMemory(inAddress, outAddress, length); - // sign extend - if (length < 32) { - byte msb = PlatformDependent.getByte(inAddress + length - 1); - final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); - PlatformDependent.setMemory(outAddress + length, Decimal256Vector.TYPE_WIDTH - length, pad); + if (LITTLE_ENDIAN) { + PlatformDependent.copyMemory(inAddress, outAddress, length); + // sign extend + if (length < TYPE_WIDTH) { + byte msb = PlatformDependent.getByte(inAddress + length - 1); + final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress + length, Decimal256Vector.TYPE_WIDTH - length, pad); + } + } else { + PlatformDependent.copyMemory(inAddress, outAddress + Decimal256Vector.TYPE_WIDTH - length, length); + // sign extend + if (length < TYPE_WIDTH) { + byte msb = PlatformDependent.getByte(inAddress); + final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress, Decimal256Vector.TYPE_WIDTH - length, pad); + } } } @@ -296,16 +321,26 @@ public void setBigEndianSafe(int index, long start, ArrowBuf buffer, int length) // not using buffer.getByte() to avoid boundary checks for every byte. long inAddress = buffer.memoryAddress() + start; long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH; - // swap bytes to convert BE to LE - for (int byteIdx = 0; byteIdx < length; ++byteIdx) { - byte val = PlatformDependent.getByte((inAddress + length - 1) - byteIdx); - PlatformDependent.putByte(outAddress + byteIdx, val); - } - // sign extend - if (length < 32) { - byte msb = PlatformDependent.getByte(inAddress); - final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); - PlatformDependent.setMemory(outAddress + length, Decimal256Vector.TYPE_WIDTH - length, pad); + if (LITTLE_ENDIAN) { + // swap bytes to convert BE to LE + for (int byteIdx = 0; byteIdx < length; ++byteIdx) { + byte val = PlatformDependent.getByte((inAddress + length - 1) - byteIdx); + PlatformDependent.putByte(outAddress + byteIdx, val); + } + // sign extend + if (length < 32) { + byte msb = PlatformDependent.getByte(inAddress); + final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress + length, Decimal256Vector.TYPE_WIDTH - length, pad); + } + } else { + PlatformDependent.copyMemory(inAddress, outAddress + Decimal256Vector.TYPE_WIDTH - length, length); + // sign extend + if (length < TYPE_WIDTH) { + byte msb = PlatformDependent.getByte(inAddress); + final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress, Decimal256Vector.TYPE_WIDTH - length, pad); + } } } @@ -329,12 +364,7 @@ public void set(int index, BigDecimal value) { */ public void set(int index, long value) { BitVectorHelper.setBit(validityBuffer, index); - final long addressOfValue = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH; - PlatformDependent.putLong(addressOfValue, value); - final long padValue = Long.signum(value) == -1 ? -1L : 0L; - PlatformDependent.putLong(addressOfValue + Long.BYTES, padValue); - PlatformDependent.putLong(addressOfValue + 2 * Long.BYTES, padValue); - PlatformDependent.putLong(addressOfValue + 3 * Long.BYTES, padValue); + DecimalUtility.writeLongToArrowBuf(value, valueBuffer, index, TYPE_WIDTH); } /** diff --git a/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java b/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java index 3fc54ba5ccc80..472c2db79860a 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java @@ -20,6 +20,7 @@ import static org.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED; import java.math.BigDecimal; +import java.nio.ByteOrder; import org.apache.arrow.memory.ArrowBuf; import org.apache.arrow.memory.BufferAllocator; @@ -43,6 +44,7 @@ */ public final class DecimalVector extends BaseFixedWidthVector { public static final byte TYPE_WIDTH = 16; + private static final boolean LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN; private final FieldReader reader; private final int precision; @@ -197,7 +199,7 @@ public void set(int index, ArrowBuf buffer) { /** * Set the decimal element at given index to the provided array of bytes. - * Decimal is now implemented as Little Endian. This API allows the user + * Decimal is now implemented as Native Endian. This API allows the user * to pass a decimal value in the form of byte array in BE byte order. * *
Consumers of Arrow code can use this API instead of first swapping @@ -218,25 +220,38 @@ public void setBigEndian(int index, byte[] value) { valueBuffer.checkBytes((long) index * TYPE_WIDTH, (long) (index + 1) * TYPE_WIDTH); long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH; - // swap bytes to convert BE to LE - for (int byteIdx = 0; byteIdx < length; ++byteIdx) { - PlatformDependent.putByte(outAddress + byteIdx, value[length - 1 - byteIdx]); - } - - if (length == TYPE_WIDTH) { - return; - } - if (length == 0) { PlatformDependent.setMemory(outAddress, DecimalVector.TYPE_WIDTH, (byte) 0); - } else if (length < TYPE_WIDTH) { - // sign extend - final byte pad = (byte) (value[0] < 0 ? 0xFF : 0x00); - PlatformDependent.setMemory(outAddress + length, DecimalVector.TYPE_WIDTH - length, pad); + return; + } + if (LITTLE_ENDIAN) { + // swap bytes to convert BE to LE + for (int byteIdx = 0; byteIdx < length; ++byteIdx) { + PlatformDependent.putByte(outAddress + byteIdx, value[length - 1 - byteIdx]); + } + + if (length == TYPE_WIDTH) { + return; + } + + if (length < TYPE_WIDTH) { + // sign extend + final byte pad = (byte) (value[0] < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress + length, DecimalVector.TYPE_WIDTH - length, pad); + return; + } } else { - throw new IllegalArgumentException( - "Invalid decimal value length. Valid length in [1 - 16], got " + length); + if (length <= TYPE_WIDTH) { + // copy data from value to outAddress + PlatformDependent.copyMemory(value, 0, outAddress + DecimalVector.TYPE_WIDTH - length, length); + // sign extend + final byte pad = (byte) (value[0] < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress, DecimalVector.TYPE_WIDTH - length, pad); + return; + } } + throw new IllegalArgumentException( + "Invalid decimal value length. Valid length in [1 - 16], got " + length); } /** @@ -255,7 +270,7 @@ public void set(int index, long start, ArrowBuf buffer) { * Sets the element at given index using the buffer whose size maybe <= 16 bytes. * @param index index to write the decimal to * @param start start of value in the buffer - * @param buffer contains the decimal in little endian bytes + * @param buffer contains the decimal in native endian bytes * @param length length of the value in the buffer */ public void setSafe(int index, long start, ArrowBuf buffer, int length) { @@ -268,12 +283,22 @@ public void setSafe(int index, long start, ArrowBuf buffer, int length) { long inAddress = buffer.memoryAddress() + start; long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH; - PlatformDependent.copyMemory(inAddress, outAddress, length); - // sign extend - if (length < 16) { - byte msb = PlatformDependent.getByte(inAddress + length - 1); - final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); - PlatformDependent.setMemory(outAddress + length, DecimalVector.TYPE_WIDTH - length, pad); + if (LITTLE_ENDIAN) { + PlatformDependent.copyMemory(inAddress, outAddress, length); + // sign extend + if (length < TYPE_WIDTH) { + byte msb = PlatformDependent.getByte(inAddress + length - 1); + final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress + length, DecimalVector.TYPE_WIDTH - length, pad); + } + } else { + PlatformDependent.copyMemory(inAddress, outAddress + DecimalVector.TYPE_WIDTH - length, length); + // sign extend + if (length < TYPE_WIDTH) { + byte msb = PlatformDependent.getByte(inAddress); + final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress, DecimalVector.TYPE_WIDTH - length, pad); + } } } @@ -296,16 +321,26 @@ public void setBigEndianSafe(int index, long start, ArrowBuf buffer, int length) // not using buffer.getByte() to avoid boundary checks for every byte. long inAddress = buffer.memoryAddress() + start; long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH; - // swap bytes to convert BE to LE - for (int byteIdx = 0; byteIdx < length; ++byteIdx) { - byte val = PlatformDependent.getByte((inAddress + length - 1) - byteIdx); - PlatformDependent.putByte(outAddress + byteIdx, val); - } - // sign extend - if (length < 16) { - byte msb = PlatformDependent.getByte(inAddress); - final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); - PlatformDependent.setMemory(outAddress + length, DecimalVector.TYPE_WIDTH - length, pad); + if (LITTLE_ENDIAN) { + // swap bytes to convert BE to LE + for (int byteIdx = 0; byteIdx < length; ++byteIdx) { + byte val = PlatformDependent.getByte((inAddress + length - 1) - byteIdx); + PlatformDependent.putByte(outAddress + byteIdx, val); + } + // sign extend + if (length < TYPE_WIDTH) { + byte msb = PlatformDependent.getByte(inAddress); + final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress + length, DecimalVector.TYPE_WIDTH - length, pad); + } + } else { + PlatformDependent.copyMemory(inAddress, outAddress + DecimalVector.TYPE_WIDTH - length, length); + // sign extend + if (length < TYPE_WIDTH) { + byte msb = PlatformDependent.getByte(inAddress); + final byte pad = (byte) (msb < 0 ? 0xFF : 0x00); + PlatformDependent.setMemory(outAddress, DecimalVector.TYPE_WIDTH - length, pad); + } } } @@ -329,7 +364,7 @@ public void set(int index, BigDecimal value) { */ public void set(int index, long value) { BitVectorHelper.setBit(validityBuffer, index); - DecimalUtility.writeLongToArrowBuf(value, valueBuffer, index); + DecimalUtility.writeLongToArrowBuf(value, valueBuffer, index, TYPE_WIDTH); } /** diff --git a/java/vector/src/main/java/org/apache/arrow/vector/ipc/message/MessageSerializer.java b/java/vector/src/main/java/org/apache/arrow/vector/ipc/message/MessageSerializer.java index 7bbee9dab943d..b2d1425270f60 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/ipc/message/MessageSerializer.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/ipc/message/MessageSerializer.java @@ -62,10 +62,10 @@ public class MessageSerializer { public static final int IPC_CONTINUATION_TOKEN = -1; /** - * Convert an array of 4 bytes to a little endian i32 value. + * Convert an array of 4 bytes in little-endian to an native-endian i32 value. * - * @param bytes byte array with minimum length of 4 - * @return converted little endian 32-bit integer + * @param bytes byte array with minimum length of 4 in little-endian + * @return converted an native-endian 32-bit integer */ public static int bytesToInt(byte[] bytes) { return ((bytes[3] & 255) << 24) + diff --git a/java/vector/src/main/java/org/apache/arrow/vector/util/DecimalUtility.java b/java/vector/src/main/java/org/apache/arrow/vector/util/DecimalUtility.java index 6f707648a75c6..f778bcb209fa9 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/util/DecimalUtility.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/util/DecimalUtility.java @@ -20,6 +20,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import org.apache.arrow.memory.ArrowBuf; @@ -31,11 +32,11 @@ public class DecimalUtility { private DecimalUtility() {} - public static final int DECIMAL_BYTE_LENGTH = 16; public static final byte [] zeroes = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; public static final byte [] minus_one = new byte[] {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + private static final boolean LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN; /** * Read an ArrowType.Decimal at the given value index in the ArrowBuf and convert to a BigDecimal @@ -46,14 +47,16 @@ public static BigDecimal getBigDecimalFromArrowBuf(ArrowBuf bytebuf, int index, byte temp; final long startIndex = (long) index * byteWidth; - // Decimal stored as little endian, need to swap bytes to make BigDecimal bytebuf.getBytes(startIndex, value, 0, byteWidth); - int stop = byteWidth / 2; - for (int i = 0, j; i < stop; i++) { - temp = value[i]; - j = (byteWidth - 1) - i; - value[i] = value[j]; - value[j] = temp; + if (LITTLE_ENDIAN) { + // Decimal stored as native endian, need to swap bytes to make BigDecimal if native endian is LE + int stop = byteWidth / 2; + for (int i = 0, j; i < stop; i++) { + temp = value[i]; + j = (byteWidth - 1) - i; + value[i] = value[j]; + value[j] = temp; + } } BigInteger unscaledValue = new BigInteger(value); return new BigDecimal(unscaledValue, scale); @@ -128,12 +131,26 @@ public static void writeBigDecimalToArrowBuf(BigDecimal value, ArrowBuf bytebuf, /** * Write the given long to the ArrowBuf at the given value index. + * This routine extends the original sign bit to a new upper area in 128-bit or 256-bit. */ - public static void writeLongToArrowBuf(long value, ArrowBuf bytebuf, int index) { - final long addressOfValue = bytebuf.memoryAddress() + (long) index * DECIMAL_BYTE_LENGTH; - PlatformDependent.putLong(addressOfValue, value); + public static void writeLongToArrowBuf(long value, ArrowBuf bytebuf, int index, int byteWidth) { + if (byteWidth != 16 && byteWidth != 32) { + throw new UnsupportedOperationException("DecimalUtility.writeLongToArrowBuf() currently supports " + + "128-bit or 256-bit width data"); + } + final long addressOfValue = bytebuf.memoryAddress() + (long) index * byteWidth; final long padValue = Long.signum(value) == -1 ? -1L : 0L; - PlatformDependent.putLong(addressOfValue + Long.BYTES, padValue); + if (LITTLE_ENDIAN) { + PlatformDependent.putLong(addressOfValue, value); + for (int i = 1; i <= (byteWidth - 8) / 8; i++) { + PlatformDependent.putLong(addressOfValue + Long.BYTES * i, padValue); + } + } else { + for (int i = 0; i < (byteWidth - 8) / 8; i++) { + PlatformDependent.putLong(addressOfValue + Long.BYTES * i, padValue); + } + PlatformDependent.putLong(addressOfValue + Long.BYTES * (byteWidth - 8) / 8, value); + } } /** @@ -151,15 +168,21 @@ private static void writeByteArrayToArrowBufHelper(byte[] bytes, ArrowBuf bytebu throw new UnsupportedOperationException("Decimal size greater than " + byteWidth + " bytes: " + bytes.length); } - // Decimal stored as little endian, need to swap data bytes before writing to ArrowBuf - byte[] bytesLE = new byte[bytes.length]; - for (int i = 0; i < bytes.length; i++) { - bytesLE[i] = bytes[bytes.length - 1 - i]; - } - - // Write LE data byte [] padBytes = bytes[0] < 0 ? minus_one : zeroes; - bytebuf.setBytes(startIndex, bytesLE, 0, bytes.length); - bytebuf.setBytes(startIndex + bytes.length, padBytes, 0, byteWidth - bytes.length); + if (LITTLE_ENDIAN) { + // Decimal stored as native-endian, need to swap data bytes before writing to ArrowBuf if LE + byte[] bytesLE = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + bytesLE[i] = bytes[bytes.length - 1 - i]; + } + + // Write LE data + bytebuf.setBytes(startIndex, bytesLE, 0, bytes.length); + bytebuf.setBytes(startIndex + bytes.length, padBytes, 0, byteWidth - bytes.length); + } else { + // Write BE data + bytebuf.setBytes(startIndex + byteWidth - bytes.length, bytes, 0, bytes.length); + bytebuf.setBytes(startIndex, padBytes, 0, byteWidth - bytes.length); + } } } diff --git a/java/vector/src/test/java/org/apache/arrow/vector/TestDecimal256Vector.java b/java/vector/src/test/java/org/apache/arrow/vector/TestDecimal256Vector.java index 7aa48f4bfb455..82c912cef2fdd 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/TestDecimal256Vector.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/TestDecimal256Vector.java @@ -210,11 +210,12 @@ public void testBigDecimalReadWrite() { } /** - * Test {@link Decimal256Vector#setBigEndian(int, byte[])} which takes BE layout input and stores in LE layout. + * Test {@link Decimal256Vector#setBigEndian(int, byte[])} which takes BE layout input and stores in native-endian + * (NE) layout. * Cases to cover: input byte array in different lengths in range [1-16] and negative values. */ @Test - public void decimalBE2LE() { + public void decimalBE2NE() { try (Decimal256Vector decimalVector = TestUtils.newVector(Decimal256Vector.class, "decimal", new ArrowType.Decimal(23, 2, 256), allocator)) { decimalVector.allocateNew(); diff --git a/java/vector/src/test/java/org/apache/arrow/vector/TestDecimalVector.java b/java/vector/src/test/java/org/apache/arrow/vector/TestDecimalVector.java index 25f480119dbc7..c7e3e436e405b 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/TestDecimalVector.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/TestDecimalVector.java @@ -216,11 +216,12 @@ public void testBigDecimalReadWrite() { } /** - * Test {@link DecimalVector#setBigEndian(int, byte[])} which takes BE layout input and stores in LE layout. + * Test {@link DecimalVector#setBigEndian(int, byte[])} which takes BE layout input and stores in native-endian (NE) + * layout. * Cases to cover: input byte array in different lengths in range [1-16] and negative values. */ @Test - public void decimalBE2LE() { + public void decimalBE2NE() { try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal", new ArrowType.Decimal(21, 2, 128), allocator)) { decimalVector.allocateNew(); @@ -270,7 +271,7 @@ public void decimalBE2LE() { } @Test - public void setUsingArrowBufOfLEInts() { + public void setUsingArrowBufOfInts() { try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal", new ArrowType.Decimal(5, 2, 128), allocator); ArrowBuf buf = allocator.buffer(8);) { @@ -299,7 +300,7 @@ public void setUsingArrowBufOfLEInts() { } @Test - public void setUsingArrowLongLEBytes() { + public void setUsingArrowLongBytes() { try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal", new ArrowType.Decimal(18, 0, 128), allocator); ArrowBuf buf = allocator.buffer(16);) { diff --git a/java/vector/src/test/java/org/apache/arrow/vector/complex/impl/TestComplexCopier.java b/java/vector/src/test/java/org/apache/arrow/vector/complex/impl/TestComplexCopier.java index 0992ffc73177d..0c560abe23deb 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/complex/impl/TestComplexCopier.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/complex/impl/TestComplexCopier.java @@ -24,6 +24,7 @@ import org.apache.arrow.memory.BufferAllocator; import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.DecimalVector; import org.apache.arrow.vector.compare.VectorEqualsVisitor; import org.apache.arrow.vector.complex.FixedSizeListVector; import org.apache.arrow.vector.complex.ListVector; @@ -526,7 +527,7 @@ public void testCopyFixedSizedListOfDecimalsVector() { to.addOrGetVector(FieldType.nullable(new ArrowType.Decimal(3, 0, 128))); DecimalHolder holder = new DecimalHolder(); - holder.buffer = allocator.buffer(DecimalUtility.DECIMAL_BYTE_LENGTH); + holder.buffer = allocator.buffer(DecimalVector.TYPE_WIDTH); ArrowType arrowType = new ArrowType.Decimal(3, 0, 128); // populate from vector @@ -535,13 +536,13 @@ public void testCopyFixedSizedListOfDecimalsVector() { writer.startList(); writer.decimal().writeDecimal(BigDecimal.valueOf(i)); - DecimalUtility.writeBigDecimalToArrowBuf(new BigDecimal(i * 2), holder.buffer, 0, /*byteWidth=*/16); + DecimalUtility.writeBigDecimalToArrowBuf(new BigDecimal(i * 2), holder.buffer, 0, DecimalVector.TYPE_WIDTH); holder.start = 0; holder.scale = 0; holder.precision = 3; writer.decimal().write(holder); - DecimalUtility.writeBigDecimalToArrowBuf(new BigDecimal(i * 3), holder.buffer, 0, /*byteWidth=*/16); + DecimalUtility.writeBigDecimalToArrowBuf(new BigDecimal(i * 3), holder.buffer, 0, DecimalVector.TYPE_WIDTH); writer.decimal().writeDecimal(0, holder.buffer, arrowType); writer.decimal().writeBigEndianBytesToDecimal(BigDecimal.valueOf(i * 4).unscaledValue().toByteArray(), diff --git a/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestComplexWriter.java b/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestComplexWriter.java index 1e6fe49575066..c378f6d53f012 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestComplexWriter.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestComplexWriter.java @@ -30,6 +30,7 @@ import org.apache.arrow.memory.RootAllocator; import org.apache.arrow.util.AutoCloseables; import org.apache.arrow.vector.BigIntVector; +import org.apache.arrow.vector.DecimalVector; import org.apache.arrow.vector.Float4Vector; import org.apache.arrow.vector.Float8Vector; import org.apache.arrow.vector.IntVector; @@ -310,7 +311,7 @@ public void listDecimalType() { listVector.allocateNew(); UnionListWriter listWriter = new UnionListWriter(listVector); DecimalHolder holder = new DecimalHolder(); - holder.buffer = allocator.buffer(DecimalUtility.DECIMAL_BYTE_LENGTH); + holder.buffer = allocator.buffer(DecimalVector.TYPE_WIDTH); ArrowType arrowType = new ArrowType.Decimal(10, 0, 128); for (int i = 0; i < COUNT; i++) { listWriter.startList(); @@ -318,13 +319,13 @@ public void listDecimalType() { if (j % 4 == 0) { listWriter.writeDecimal(new BigDecimal(j)); } else if (j % 4 == 1) { - DecimalUtility.writeBigDecimalToArrowBuf(new BigDecimal(j), holder.buffer, 0, 16); + DecimalUtility.writeBigDecimalToArrowBuf(new BigDecimal(j), holder.buffer, 0, DecimalVector.TYPE_WIDTH); holder.start = 0; holder.scale = 0; holder.precision = 10; listWriter.write(holder); } else if (j % 4 == 2) { - DecimalUtility.writeBigDecimalToArrowBuf(new BigDecimal(j), holder.buffer, 0, 16); + DecimalUtility.writeBigDecimalToArrowBuf(new BigDecimal(j), holder.buffer, 0, DecimalVector.TYPE_WIDTH); listWriter.writeDecimal(0, holder.buffer, arrowType); } else { byte[] value = BigDecimal.valueOf(j).unscaledValue().toByteArray(); diff --git a/java/vector/src/test/java/org/apache/arrow/vector/util/DecimalUtilityTest.java b/java/vector/src/test/java/org/apache/arrow/vector/util/DecimalUtilityTest.java index 2e255e6dda2c5..804092ed94ac7 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/util/DecimalUtilityTest.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/util/DecimalUtilityTest.java @@ -32,6 +32,25 @@ public class DecimalUtilityTest { private static final BigInteger[] MIN_BIG_INT = new BigInteger[]{MAX_BIG_INT[0].multiply(BigInteger.valueOf(-1)), MAX_BIG_INT[1].multiply(BigInteger.valueOf(-1))}; + @Test + public void testSetLongInDecimalArrowBuf() { + int[] byteLengths = new int[]{16, 32}; + for (int x = 0; x < 2; x++) { + try (BufferAllocator allocator = new RootAllocator(128); + ArrowBuf buf = allocator.buffer(byteLengths[x]); + ) { + int [] intValues = new int [] {Integer.MAX_VALUE, Integer.MIN_VALUE, 0}; + for (int val : intValues) { + buf.clear(); + DecimalUtility.writeLongToArrowBuf((long) val, buf, 0, byteLengths[x]); + BigDecimal actual = DecimalUtility.getBigDecimalFromArrowBuf(buf, 0, 0, byteLengths[x]); + BigDecimal expected = BigDecimal.valueOf(val); + Assert.assertEquals(expected, actual); + } + } + } + } + @Test public void testSetByteArrayInDecimalArrowBuf() { int[] byteLengths = new int[]{16, 32};