]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/java/vector/src/test/java/org/apache/arrow/vector/TestDecimalVector.java
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / java / vector / src / test / java / org / apache / arrow / vector / TestDecimalVector.java
CommitLineData
1d09f67e
TL
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.arrow.vector;
19
20import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.assertTrue;
22import static org.junit.Assert.fail;
23
24import java.math.BigDecimal;
25import java.math.BigInteger;
26
27import org.apache.arrow.memory.ArrowBuf;
28import org.apache.arrow.memory.BufferAllocator;
29import org.apache.arrow.vector.types.pojo.ArrowType;
30import org.junit.After;
31import org.junit.Before;
32import org.junit.Test;
33
34public class TestDecimalVector {
35
36 private static long[] intValues;
37
38 static {
39 intValues = new long[60];
40 for (int i = 0; i < intValues.length / 2; i++) {
41 intValues[i] = 1 << i + 1;
42 intValues[2 * i] = -1 * (1 << i + 1);
43 }
44 }
45
46 private int scale = 3;
47
48 private BufferAllocator allocator;
49
50 @Before
51 public void init() {
52 allocator = new DirtyRootAllocator(Long.MAX_VALUE, (byte) 100);
53 }
54
55 @After
56 public void terminate() throws Exception {
57 allocator.close();
58 }
59
60 @Test
61 public void testValuesWriteRead() {
62 try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal",
63 new ArrowType.Decimal(10, scale, 128), allocator);) {
64
65 try (DecimalVector oldConstructor = new DecimalVector("decimal", allocator, 10, scale);) {
66 assertEquals(decimalVector.getField().getType(), oldConstructor.getField().getType());
67 }
68
69 decimalVector.allocateNew();
70 BigDecimal[] values = new BigDecimal[intValues.length];
71 for (int i = 0; i < intValues.length; i++) {
72 BigDecimal decimal = new BigDecimal(BigInteger.valueOf(intValues[i]), scale);
73 values[i] = decimal;
74 decimalVector.setSafe(i, decimal);
75 }
76
77 decimalVector.setValueCount(intValues.length);
78
79 for (int i = 0; i < intValues.length; i++) {
80 BigDecimal value = decimalVector.getObject(i);
81 assertEquals("unexpected data at index: " + i, values[i], value);
82 }
83 }
84 }
85
86 @Test
87 public void testBigDecimalDifferentScaleAndPrecision() {
88 try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal",
89 new ArrowType.Decimal(4, 2, 128), allocator);) {
90 decimalVector.allocateNew();
91
92 // test BigDecimal with different scale
93 boolean hasError = false;
94 try {
95 BigDecimal decimal = new BigDecimal(BigInteger.valueOf(0), 3);
96 decimalVector.setSafe(0, decimal);
97 } catch (UnsupportedOperationException ue) {
98 hasError = true;
99 } finally {
100 assertTrue(hasError);
101 }
102
103 // test BigDecimal with larger precision than initialized
104 hasError = false;
105 try {
106 BigDecimal decimal = new BigDecimal(BigInteger.valueOf(12345), 2);
107 decimalVector.setSafe(0, decimal);
108 } catch (UnsupportedOperationException ue) {
109 hasError = true;
110 } finally {
111 assertTrue(hasError);
112 }
113 }
114 }
115
116 @Test
117 public void testWriteBigEndian() {
118 try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal",
119 new ArrowType.Decimal(38, 9, 128), allocator);) {
120 decimalVector.allocateNew();
121 BigDecimal decimal1 = new BigDecimal("123456789.000000000");
122 BigDecimal decimal2 = new BigDecimal("11.123456789");
123 BigDecimal decimal3 = new BigDecimal("1.000000000");
124 BigDecimal decimal4 = new BigDecimal("0.111111111");
125 BigDecimal decimal5 = new BigDecimal("987654321.123456789");
126 BigDecimal decimal6 = new BigDecimal("222222222222.222222222");
127 BigDecimal decimal7 = new BigDecimal("7777777777777.666666667");
128 BigDecimal decimal8 = new BigDecimal("1212121212.343434343");
129
130 byte[] decimalValue1 = decimal1.unscaledValue().toByteArray();
131 byte[] decimalValue2 = decimal2.unscaledValue().toByteArray();
132 byte[] decimalValue3 = decimal3.unscaledValue().toByteArray();
133 byte[] decimalValue4 = decimal4.unscaledValue().toByteArray();
134 byte[] decimalValue5 = decimal5.unscaledValue().toByteArray();
135 byte[] decimalValue6 = decimal6.unscaledValue().toByteArray();
136 byte[] decimalValue7 = decimal7.unscaledValue().toByteArray();
137 byte[] decimalValue8 = decimal8.unscaledValue().toByteArray();
138
139 decimalVector.setBigEndian(0, decimalValue1);
140 decimalVector.setBigEndian(1, decimalValue2);
141 decimalVector.setBigEndian(2, decimalValue3);
142 decimalVector.setBigEndian(3, decimalValue4);
143 decimalVector.setBigEndian(4, decimalValue5);
144 decimalVector.setBigEndian(5, decimalValue6);
145 decimalVector.setBigEndian(6, decimalValue7);
146 decimalVector.setBigEndian(7, decimalValue8);
147
148 decimalVector.setValueCount(8);
149 assertEquals(8, decimalVector.getValueCount());
150 assertEquals(decimal1, decimalVector.getObject(0));
151 assertEquals(decimal2, decimalVector.getObject(1));
152 assertEquals(decimal3, decimalVector.getObject(2));
153 assertEquals(decimal4, decimalVector.getObject(3));
154 assertEquals(decimal5, decimalVector.getObject(4));
155 assertEquals(decimal6, decimalVector.getObject(5));
156 assertEquals(decimal7, decimalVector.getObject(6));
157 assertEquals(decimal8, decimalVector.getObject(7));
158 }
159 }
160
161 @Test
162 public void testLongReadWrite() {
163 try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal",
164 new ArrowType.Decimal(38, 0, 128), allocator)) {
165 decimalVector.allocateNew();
166
167 long[] longValues = {0L, -2L, Long.MAX_VALUE, Long.MIN_VALUE, 187L};
168
169 for (int i = 0; i < longValues.length; ++i) {
170 decimalVector.set(i, longValues[i]);
171 }
172
173 decimalVector.setValueCount(longValues.length);
174
175 for (int i = 0; i < longValues.length; ++i) {
176 assertEquals(new BigDecimal(longValues[i]), decimalVector.getObject(i));
177 }
178 }
179 }
180
181
182 @Test
183 public void testBigDecimalReadWrite() {
184 try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal",
185 new ArrowType.Decimal(38, 9, 128), allocator);) {
186 decimalVector.allocateNew();
187 BigDecimal decimal1 = new BigDecimal("123456789.000000000");
188 BigDecimal decimal2 = new BigDecimal("11.123456789");
189 BigDecimal decimal3 = new BigDecimal("1.000000000");
190 BigDecimal decimal4 = new BigDecimal("-0.111111111");
191 BigDecimal decimal5 = new BigDecimal("-987654321.123456789");
192 BigDecimal decimal6 = new BigDecimal("-222222222222.222222222");
193 BigDecimal decimal7 = new BigDecimal("7777777777777.666666667");
194 BigDecimal decimal8 = new BigDecimal("1212121212.343434343");
195
196 decimalVector.set(0, decimal1);
197 decimalVector.set(1, decimal2);
198 decimalVector.set(2, decimal3);
199 decimalVector.set(3, decimal4);
200 decimalVector.set(4, decimal5);
201 decimalVector.set(5, decimal6);
202 decimalVector.set(6, decimal7);
203 decimalVector.set(7, decimal8);
204
205 decimalVector.setValueCount(8);
206 assertEquals(8, decimalVector.getValueCount());
207 assertEquals(decimal1, decimalVector.getObject(0));
208 assertEquals(decimal2, decimalVector.getObject(1));
209 assertEquals(decimal3, decimalVector.getObject(2));
210 assertEquals(decimal4, decimalVector.getObject(3));
211 assertEquals(decimal5, decimalVector.getObject(4));
212 assertEquals(decimal6, decimalVector.getObject(5));
213 assertEquals(decimal7, decimalVector.getObject(6));
214 assertEquals(decimal8, decimalVector.getObject(7));
215 }
216 }
217
218 /**
219 * Test {@link DecimalVector#setBigEndian(int, byte[])} which takes BE layout input and stores in native-endian (NE)
220 * layout.
221 * Cases to cover: input byte array in different lengths in range [1-16] and negative values.
222 */
223 @Test
224 public void decimalBE2NE() {
225 try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal",
226 new ArrowType.Decimal(21, 2, 128), allocator)) {
227 decimalVector.allocateNew();
228
229 BigInteger[] testBigInts = new BigInteger[] {
230 new BigInteger("0"),
231 new BigInteger("-1"),
232 new BigInteger("23"),
233 new BigInteger("234234"),
234 new BigInteger("-234234234"),
235 new BigInteger("234234234234"),
236 new BigInteger("-56345345345345"),
237 new BigInteger("29823462983462893462934679234653456345"), // converts to 16 byte array
238 new BigInteger("-3894572983475982374598324598234346536"), // converts to 16 byte array
239 new BigInteger("-345345"),
240 new BigInteger("754533")
241 };
242
243 int insertionIdx = 0;
244 insertionIdx++; // insert a null
245 for (BigInteger val : testBigInts) {
246 decimalVector.setBigEndian(insertionIdx++, val.toByteArray());
247 }
248 insertionIdx++; // insert a null
249 // insert a zero length buffer
250 decimalVector.setBigEndian(insertionIdx++, new byte[0]);
251
252 // Try inserting a buffer larger than 16bytes and expect a failure
253 try {
254 decimalVector.setBigEndian(insertionIdx, new byte[17]);
255 fail("above statement should have failed");
256 } catch (IllegalArgumentException ex) {
257 assertTrue(ex.getMessage().equals("Invalid decimal value length. Valid length in [1 - 16], got 17"));
258 }
259 decimalVector.setValueCount(insertionIdx);
260
261 // retrieve values and check if they are correct
262 int outputIdx = 0;
263 assertTrue(decimalVector.isNull(outputIdx++));
264 for (BigInteger expected : testBigInts) {
265 final BigDecimal actual = decimalVector.getObject(outputIdx++);
266 assertEquals(expected, actual.unscaledValue());
267 }
268 assertTrue(decimalVector.isNull(outputIdx++));
269 assertEquals(BigInteger.valueOf(0), decimalVector.getObject(outputIdx).unscaledValue());
270 }
271 }
272
273 @Test
274 public void setUsingArrowBufOfInts() {
275 try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal",
276 new ArrowType.Decimal(5, 2, 128), allocator);
277 ArrowBuf buf = allocator.buffer(8);) {
278 decimalVector.allocateNew();
279
280 // add a positive value equivalent to 705.32
281 int val = 70532;
282 buf.setInt(0, val);
283 decimalVector.setSafe(0, 0, buf, 4);
284
285 // add a -ve value equivalent to -705.32
286 val = -70532;
287 buf.setInt(4, val);
288 decimalVector.setSafe(1, 4, buf, 4);
289
290 decimalVector.setValueCount(2);
291
292 BigDecimal [] expectedValues = new BigDecimal[] {BigDecimal.valueOf(705.32), BigDecimal
293 .valueOf(-705.32)};
294 for (int i = 0; i < 2; i ++) {
295 BigDecimal value = decimalVector.getObject(i);
296 assertEquals(expectedValues[i], value);
297 }
298 }
299
300 }
301
302 @Test
303 public void setUsingArrowLongBytes() {
304 try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal",
305 new ArrowType.Decimal(18, 0, 128), allocator);
306 ArrowBuf buf = allocator.buffer(16);) {
307 decimalVector.allocateNew();
308
309 long val = Long.MAX_VALUE;
310 buf.setLong(0, val);
311 decimalVector.setSafe(0, 0, buf, 8);
312
313 val = Long.MIN_VALUE;
314 buf.setLong(8, val);
315 decimalVector.setSafe(1, 8, buf, 8);
316
317 decimalVector.setValueCount(2);
318
319 BigDecimal [] expectedValues = new BigDecimal[] {BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal
320 .valueOf(Long.MIN_VALUE)};
321 for (int i = 0; i < 2; i ++) {
322 BigDecimal value = decimalVector.getObject(i);
323 assertEquals(expectedValues[i], value);
324 }
325 }
326 }
327
328 @Test
329 public void setUsingArrowBufOfBEBytes() {
330 try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal",
331 new ArrowType.Decimal(5, 2, 128), allocator);
332 ArrowBuf buf = allocator.buffer(9);) {
333 BigDecimal [] expectedValues = new BigDecimal[] {BigDecimal.valueOf(705.32), BigDecimal
334 .valueOf(-705.32), BigDecimal.valueOf(705.32)};
335 verifyWritingArrowBufWithBigEndianBytes(decimalVector, buf, expectedValues, 3);
336 }
337
338 try (DecimalVector decimalVector = TestUtils.newVector(DecimalVector.class, "decimal",
339 new ArrowType.Decimal(36, 2, 128), allocator);
340 ArrowBuf buf = allocator.buffer(45);) {
341 BigDecimal[] expectedValues = new BigDecimal[] {new BigDecimal("2982346298346289346293467923465345.63"),
342 new BigDecimal("-2982346298346289346293467923465345.63"),
343 new BigDecimal("2982346298346289346293467923465345.63")};
344 verifyWritingArrowBufWithBigEndianBytes(decimalVector, buf, expectedValues, 15);
345 }
346 }
347
348 private void verifyWritingArrowBufWithBigEndianBytes(DecimalVector decimalVector,
349 ArrowBuf buf, BigDecimal[] expectedValues,
350 int length) {
351 decimalVector.allocateNew();
352 for (int i = 0; i < expectedValues.length; i++) {
353 byte []bigEndianBytes = expectedValues[i].unscaledValue().toByteArray();
354 buf.setBytes(length * i , bigEndianBytes, 0 , bigEndianBytes.length);
355 decimalVector.setBigEndianSafe(i, length * i, buf, bigEndianBytes.length);
356 }
357
358 decimalVector.setValueCount(3);
359
360 for (int i = 0; i < expectedValues.length; i ++) {
361 BigDecimal value = decimalVector.getObject(i);
362 assertEquals(expectedValues[i], value);
363 }
364 }
365}