|
16 | 16 | */ |
17 | 17 | package org.apache.arrow.vector.complex.impl; |
18 | 18 |
|
| 19 | +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; |
| 20 | +import static org.junit.jupiter.api.Assertions.assertEquals; |
19 | 21 | import static org.junit.jupiter.api.Assertions.assertThrows; |
20 | 22 | import static org.junit.jupiter.api.Assertions.assertTrue; |
21 | 23 |
|
22 | 24 | import java.math.BigDecimal; |
| 25 | +import java.util.Arrays; |
23 | 26 | import java.util.UUID; |
24 | 27 | import org.apache.arrow.memory.BufferAllocator; |
25 | 28 | import org.apache.arrow.memory.RootAllocator; |
|
36 | 39 | import org.apache.arrow.vector.complex.writer.FieldWriter; |
37 | 40 | import org.apache.arrow.vector.extension.UuidType; |
38 | 41 | import org.apache.arrow.vector.holders.DecimalHolder; |
| 42 | +import org.apache.arrow.vector.types.TimeUnit; |
39 | 43 | import org.apache.arrow.vector.types.Types; |
40 | 44 | import org.apache.arrow.vector.types.pojo.ArrowType; |
| 45 | +import org.apache.arrow.vector.types.pojo.Field; |
41 | 46 | import org.apache.arrow.vector.types.pojo.FieldType; |
42 | 47 | import org.apache.arrow.vector.util.DecimalUtility; |
43 | 48 | import org.junit.jupiter.api.AfterEach; |
@@ -954,4 +959,125 @@ public void testCopyStructVectorWithExtensionType() { |
954 | 959 | assertTrue(VectorEqualsVisitor.vectorEquals(from, to)); |
955 | 960 | } |
956 | 961 | } |
| 962 | + |
| 963 | + @Test |
| 964 | + public void testCopyListOfTimeStampNanoTZVector() { |
| 965 | + try (ListVector from = ListVector.empty("v", allocator); |
| 966 | + ListVector to = ListVector.empty("v", allocator)) { |
| 967 | + from.addOrGetVector(FieldType.nullable(new ArrowType.Timestamp(TimeUnit.NANOSECOND, "UTC"))); |
| 968 | + to.addOrGetVector(FieldType.nullable(new ArrowType.Timestamp(TimeUnit.NANOSECOND, "UTC"))); |
| 969 | + |
| 970 | + UnionListWriter listWriter = from.getWriter(); |
| 971 | + listWriter.allocate(); |
| 972 | + for (int i = 0; i < COUNT; i++) { |
| 973 | + listWriter.setPosition(i); |
| 974 | + listWriter.startList(); |
| 975 | + listWriter.timeStampNanoTZ().writeTimeStampNanoTZ(i * 1_000_000L); |
| 976 | + listWriter.timeStampNanoTZ().writeTimeStampNanoTZ(i * 2_000_000L); |
| 977 | + listWriter.endList(); |
| 978 | + } |
| 979 | + from.setValueCount(COUNT); |
| 980 | + |
| 981 | + // copy values |
| 982 | + FieldReader in = from.getReader(); |
| 983 | + FieldWriter out = to.getWriter(); |
| 984 | + for (int i = 0; i < COUNT; i++) { |
| 985 | + in.setPosition(i); |
| 986 | + out.setPosition(i); |
| 987 | + ComplexCopier.copy(in, out); |
| 988 | + } |
| 989 | + to.setValueCount(COUNT); |
| 990 | + |
| 991 | + // validate equals |
| 992 | + assertTrue(VectorEqualsVisitor.vectorEquals(from, to)); |
| 993 | + } |
| 994 | + } |
| 995 | + |
| 996 | + @Test |
| 997 | + public void testCopyStructOfTimeStampNanoTZVector() { |
| 998 | + try (final StructVector from = StructVector.empty("v", allocator); |
| 999 | + final StructVector to = StructVector.empty("v", allocator)) { |
| 1000 | + from.allocateNewSafe(); |
| 1001 | + |
| 1002 | + NullableStructWriter structWriter = from.getWriter(); |
| 1003 | + for (int i = 0; i < COUNT; i++) { |
| 1004 | + structWriter.setPosition(i); |
| 1005 | + structWriter.start(); |
| 1006 | + structWriter.timeStampNanoTZ("ts", "UTC").writeTimeStampNanoTZ(i * 1_000_000L); |
| 1007 | + structWriter.end(); |
| 1008 | + } |
| 1009 | + from.setValueCount(COUNT); |
| 1010 | + |
| 1011 | + // copy values |
| 1012 | + FieldReader in = from.getReader(); |
| 1013 | + FieldWriter out = to.getWriter(); |
| 1014 | + for (int i = 0; i < COUNT; i++) { |
| 1015 | + in.setPosition(i); |
| 1016 | + out.setPosition(i); |
| 1017 | + ComplexCopier.copy(in, out); |
| 1018 | + } |
| 1019 | + to.setValueCount(COUNT); |
| 1020 | + |
| 1021 | + // validate equals |
| 1022 | + assertTrue(VectorEqualsVisitor.vectorEquals(from, to)); |
| 1023 | + } |
| 1024 | + } |
| 1025 | + |
| 1026 | + @Test |
| 1027 | + public void testCopyMapOfTimeStampNanoTZVector() { |
| 1028 | + // Before the fix ComplexCopier.getMapWriterForReader threw |
| 1029 | + // UnsupportedOperationException for a TimeStamp*TZ map value. The map value |
| 1030 | + // child is pre-typed so the reader reports TIMESTAMPNANOTZ and the map case |
| 1031 | + // is actually exercised. vectorEquals is not asserted because the MapWriter |
| 1032 | + // scalar API has no timezone overload (unlike StructWriter), so the copied |
| 1033 | + // value child does not round-trip to the same timezone; this test locks in |
| 1034 | + // that copying the map no longer throws. |
| 1035 | + Field key = new Field("key", FieldType.notNullable(new ArrowType.Int(32, true)), null); |
| 1036 | + Field value = |
| 1037 | + new Field( |
| 1038 | + "value", |
| 1039 | + FieldType.nullable(new ArrowType.Timestamp(TimeUnit.NANOSECOND, "UTC")), |
| 1040 | + null); |
| 1041 | + Field entries = |
| 1042 | + new Field( |
| 1043 | + MapVector.DATA_VECTOR_NAME, |
| 1044 | + FieldType.notNullable(ArrowType.Struct.INSTANCE), |
| 1045 | + Arrays.asList(key, value)); |
| 1046 | + Field mapField = |
| 1047 | + new Field("v", FieldType.nullable(new ArrowType.Map(false)), Arrays.asList(entries)); |
| 1048 | + |
| 1049 | + try (final MapVector from = (MapVector) mapField.createVector(allocator); |
| 1050 | + final MapVector to = MapVector.empty("v", allocator, false)) { |
| 1051 | + |
| 1052 | + from.allocateNew(); |
| 1053 | + |
| 1054 | + UnionMapWriter mapWriter = from.getWriter(); |
| 1055 | + for (int i = 0; i < COUNT; i++) { |
| 1056 | + mapWriter.setPosition(i); |
| 1057 | + mapWriter.startMap(); |
| 1058 | + mapWriter.startEntry(); |
| 1059 | + mapWriter.key().integer().writeInt(i); |
| 1060 | + mapWriter.value().timeStampNanoTZ().writeTimeStampNanoTZ(i * 1_000_000L); |
| 1061 | + mapWriter.endEntry(); |
| 1062 | + mapWriter.endMap(); |
| 1063 | + } |
| 1064 | + |
| 1065 | + from.setValueCount(COUNT); |
| 1066 | + |
| 1067 | + // copy values |
| 1068 | + FieldReader in = from.getReader(); |
| 1069 | + FieldWriter out = to.getWriter(); |
| 1070 | + assertDoesNotThrow( |
| 1071 | + () -> { |
| 1072 | + for (int i = 0; i < COUNT; i++) { |
| 1073 | + in.setPosition(i); |
| 1074 | + out.setPosition(i); |
| 1075 | + ComplexCopier.copy(in, out); |
| 1076 | + } |
| 1077 | + }); |
| 1078 | + to.setValueCount(COUNT); |
| 1079 | + |
| 1080 | + assertEquals(from.getValueCount(), to.getValueCount()); |
| 1081 | + } |
| 1082 | + } |
957 | 1083 | } |
0 commit comments