Skip to content

Commit 05416fd

Browse files
committed
apacheGH-725: Added ExtensionReader (apache#726)
## What's Changed ExtensionReader was added to support reading extension types from a complex vector. It contains **read(ExtensionHolder)** method for reading to the holder. And **readObject** - for reading the value explicitly. Closes apache#725. (cherry picked from commit e6da71e871a3678a737a88dbe79491b4111496b4)
1 parent da5a27b commit 05416fd

File tree

12 files changed

+332
-32
lines changed

12 files changed

+332
-32
lines changed

java/vector/src/main/codegen/templates/AbstractFieldReader.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,23 @@ public void copyAsField(String name, ${name}Writer writer) {
108108
}
109109

110110
</#list></#list>
111+
112+
public void read(ExtensionHolder holder) {
113+
fail("Extension");
114+
}
115+
116+
public void read(int arrayIndex, ExtensionHolder holder) {
117+
fail("RepeatedExtension");
118+
}
119+
120+
public void copyAsValue(AbstractExtensionTypeWriter writer) {
121+
fail("CopyAsValueExtension");
122+
}
123+
124+
public void copyAsField(String name, AbstractExtensionTypeWriter writer) {
125+
fail("CopyAsFieldExtension");
126+
}
127+
111128
public FieldReader reader(String name) {
112129
fail("reader(String name)");
113130
return null;

java/vector/src/main/codegen/templates/BaseReader.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,17 @@ public interface BaseReader extends Positionable{
4444
public interface StructReader extends BaseReader, Iterable<String>{
4545
FieldReader reader(String name);
4646
}
47-
47+
4848
public interface RepeatedStructReader extends StructReader{
4949
boolean next();
5050
int size();
5151
void copyAsValue(StructWriter writer);
5252
}
53-
53+
5454
public interface ListReader extends BaseReader{
55-
FieldReader reader();
55+
FieldReader reader();
5656
}
57-
57+
5858
public interface RepeatedListReader extends ListReader{
5959
boolean next();
6060
int size();
@@ -70,16 +70,15 @@ public interface RepeatedMapReader extends MapReader{
7070
int size();
7171
void copyAsValue(MapWriter writer);
7272
}
73-
74-
public interface ScalarReader extends
75-
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first /> ${name}Reader, </#list></#list>
73+
74+
public interface ScalarReader extends
75+
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first /> ${name}Reader, </#list></#list>
7676
BaseReader {}
77-
77+
7878
interface ComplexReader{
7979
StructReader rootAsStruct();
8080
ListReader rootAsList();
8181
boolean rootIsStruct();
8282
boolean ok();
8383
}
8484
}
85-

java/vector/src/main/codegen/templates/NullReader.java

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@
3333
*/
3434
@SuppressWarnings("unused")
3535
public class NullReader extends AbstractBaseReader implements FieldReader{
36-
36+
3737
public static final NullReader INSTANCE = new NullReader();
3838
public static final NullReader EMPTY_LIST_INSTANCE = new NullReader(MinorType.NULL);
3939
public static final NullReader EMPTY_STRUCT_INSTANCE = new NullReader(MinorType.STRUCT);
4040
private MinorType type;
41-
41+
4242
private NullReader(){
4343
super();
4444
type = MinorType.NULL;
@@ -77,71 +77,72 @@ public void read(Nullable${name}Holder holder){
7777
public void read(int arrayIndex, ${name}Holder holder){
7878
throw new ArrayIndexOutOfBoundsException();
7979
}
80-
80+
8181
public void copyAsValue(${minor.class}Writer writer){}
8282
public void copyAsField(String name, ${minor.class}Writer writer){}
8383

8484
public void read(int arrayIndex, Nullable${name}Holder holder){
8585
throw new ArrayIndexOutOfBoundsException();
8686
}
8787
</#list></#list>
88-
88+
89+
public void read(ExtensionHolder holder) {
90+
holder.isSet = 0;
91+
}
92+
8993
public int size(){
9094
return 0;
9195
}
92-
96+
9397
public boolean isSet(){
9498
return false;
9599
}
96-
100+
97101
public boolean next(){
98102
return false;
99103
}
100-
104+
101105
public RepeatedStructReader struct(){
102106
return this;
103107
}
104-
108+
105109
public RepeatedListReader list(){
106110
return this;
107111
}
108-
112+
109113
public StructReader struct(String name){
110114
return this;
111115
}
112-
116+
113117
public ListReader list(String name){
114118
return this;
115119
}
116-
120+
117121
public FieldReader reader(String name){
118122
return this;
119123
}
120-
124+
121125
public FieldReader reader(){
122126
return this;
123127
}
124-
128+
125129
private void fail(String name){
126130
throw new IllegalArgumentException(String.format("You tried to read a %s type when you are using a ValueReader of type %s.", name, this.getClass().getSimpleName()));
127131
}
128-
132+
129133
<#list ["Object", "BigDecimal", "Short", "Integer", "Long", "Boolean",
130134
"LocalDateTime", "Duration", "Period", "Double", "Float",
131135
"Character", "Text", "String", "Byte", "byte[]", "PeriodDuration"] as friendlyType>
132136
<#assign safeType=friendlyType />
133137
<#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
134-
138+
135139
public ${friendlyType} read${safeType}(int arrayIndex){
136140
return null;
137141
}
138-
142+
139143
public ${friendlyType} read${safeType}(){
140144
return null;
141145
}
142146
</#list>
143-
144-
}
145-
146-
147147

148+
}

java/vector/src/main/codegen/templates/PromotableWriter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,10 @@ public void addExtensionTypeWriterFactory(ExtensionTypeWriterFactory factory) {
550550
getWriter(MinorType.EXTENSIONTYPE).addExtensionTypeWriterFactory(factory);
551551
}
552552

553+
public void addExtensionTypeWriterFactory(ExtensionTypeWriterFactory factory, ArrowType arrowType) {
554+
getWriter(MinorType.EXTENSIONTYPE, arrowType).addExtensionTypeWriterFactory(factory);
555+
}
556+
553557
@Override
554558
public void allocate() {
555559
getWriter().allocate();

java/vector/src/main/codegen/templates/UnionListWriter.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public class Union${listName}Writer extends AbstractFieldWriter {
5353
private boolean inStruct = false;
5454
private boolean listStarted = false;
5555
private String structName;
56+
private ArrowType extensionType;
5657
<#if listName == "LargeList" || listName == "LargeListView">
5758
private static final long OFFSET_WIDTH = 8;
5859
<#else>
@@ -203,9 +204,9 @@ public MapWriter map(String name, boolean keysSorted) {
203204
204205
@Override
205206
public ExtensionWriter extension(ArrowType arrowType) {
207+
this.extensionType = arrowType;
206208
return this;
207209
}
208-
209210
@Override
210211
public ExtensionWriter extension(String name, ArrowType arrowType) {
211212
ExtensionWriter extensionWriter = writer.extension(name, arrowType);
@@ -342,12 +343,11 @@ public void writeExtension(Object value) {
342343
343344
@Override
344345
public void addExtensionTypeWriterFactory(ExtensionTypeWriterFactory var1) {
345-
writer.addExtensionTypeWriterFactory(var1);
346+
writer.addExtensionTypeWriterFactory(var1, extensionType);
346347
}
347348
348349
public void write(ExtensionHolder var1) {
349350
writer.write(var1);
350-
writer.setPosition(writer.idx() + 1);
351351
}
352352
353353
<#list vv.types as type>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
package org.apache.arrow.vector.complex.reader;
18+
19+
import org.apache.arrow.vector.holders.ExtensionHolder;
20+
21+
/** Interface for reading extension types. Extends the functionality of {@link BaseReader}. */
22+
public interface ExtensionReader extends BaseReader {
23+
24+
/**
25+
* Reads to the given extension holder.
26+
*
27+
* @param holder the {@link ExtensionHolder} to read
28+
*/
29+
void read(ExtensionHolder holder);
30+
31+
/**
32+
* Reads and returns an object representation of the extension type.
33+
*
34+
* @return the object representation of the extension type
35+
*/
36+
Object readObject();
37+
38+
/**
39+
* Checks if the current value is set.
40+
*
41+
* @return true if the value is set, false otherwise
42+
*/
43+
boolean isSet();
44+
}

java/vector/src/test/java/org/apache/arrow/vector/TestListVector.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,22 @@
2323
import static org.junit.jupiter.api.Assertions.assertThrows;
2424
import static org.junit.jupiter.api.Assertions.assertTrue;
2525

26+
import java.nio.ByteBuffer;
2627
import java.util.ArrayList;
2728
import java.util.Arrays;
2829
import java.util.List;
30+
import java.util.UUID;
2931
import org.apache.arrow.memory.ArrowBuf;
3032
import org.apache.arrow.memory.BufferAllocator;
3133
import org.apache.arrow.util.AutoCloseables;
3234
import org.apache.arrow.vector.complex.BaseRepeatedValueVector;
3335
import org.apache.arrow.vector.complex.ListVector;
36+
import org.apache.arrow.vector.complex.impl.UnionListReader;
3437
import org.apache.arrow.vector.complex.impl.UnionListWriter;
38+
import org.apache.arrow.vector.complex.impl.UuidWriterFactory;
3539
import org.apache.arrow.vector.complex.reader.FieldReader;
40+
import org.apache.arrow.vector.complex.writer.BaseWriter.ExtensionWriter;
41+
import org.apache.arrow.vector.holder.UuidHolder;
3642
import org.apache.arrow.vector.holders.DurationHolder;
3743
import org.apache.arrow.vector.holders.FixedSizeBinaryHolder;
3844
import org.apache.arrow.vector.holders.TimeStampMilliTZHolder;
@@ -41,6 +47,7 @@
4147
import org.apache.arrow.vector.types.pojo.ArrowType;
4248
import org.apache.arrow.vector.types.pojo.Field;
4349
import org.apache.arrow.vector.types.pojo.FieldType;
50+
import org.apache.arrow.vector.types.pojo.UuidType;
4451
import org.apache.arrow.vector.util.TransferPair;
4552
import org.junit.jupiter.api.AfterEach;
4653
import org.junit.jupiter.api.BeforeEach;
@@ -1198,6 +1205,71 @@ public void testGetTransferPairWithField() {
11981205
}
11991206
}
12001207

1208+
@Test
1209+
public void testListVectorWithExtensionType() throws Exception {
1210+
final FieldType type = FieldType.nullable(new UuidType());
1211+
try (final ListVector inVector = new ListVector("list", allocator, type, null)) {
1212+
UnionListWriter writer = inVector.getWriter();
1213+
writer.allocate();
1214+
writer.setPosition(0);
1215+
UUID u1 = UUID.randomUUID();
1216+
UUID u2 = UUID.randomUUID();
1217+
writer.startList();
1218+
ExtensionWriter extensionWriter = writer.extension(new UuidType());
1219+
extensionWriter.addExtensionTypeWriterFactory(new UuidWriterFactory());
1220+
extensionWriter.writeExtension(u1);
1221+
extensionWriter.writeExtension(u2);
1222+
writer.endList();
1223+
1224+
writer.setValueCount(1);
1225+
1226+
FieldReader reader = inVector.getReader();
1227+
assertTrue(reader.isSet(), "shouldn't be null");
1228+
Object result = inVector.getObject(0);
1229+
ArrayList<UUID> resultSet = (ArrayList<UUID>) result;
1230+
assertEquals(2, resultSet.size());
1231+
assertEquals(u1, resultSet.get(0));
1232+
assertEquals(u2, resultSet.get(1));
1233+
}
1234+
}
1235+
1236+
@Test
1237+
public void testListVectorReaderForExtensionType() throws Exception {
1238+
final FieldType type = FieldType.nullable(new UuidType());
1239+
try (final ListVector inVector = new ListVector("list", allocator, type, null)) {
1240+
UnionListWriter writer = inVector.getWriter();
1241+
writer.allocate();
1242+
writer.setPosition(0);
1243+
UUID u1 = UUID.randomUUID();
1244+
UUID u2 = UUID.randomUUID();
1245+
writer.startList();
1246+
ExtensionWriter extensionWriter = writer.extension(new UuidType());
1247+
extensionWriter.addExtensionTypeWriterFactory(new UuidWriterFactory());
1248+
extensionWriter.writeExtension(u1);
1249+
extensionWriter.writeExtension(u2);
1250+
writer.endList();
1251+
1252+
writer.setValueCount(1);
1253+
1254+
UnionListReader reader = inVector.getReader();
1255+
assertTrue(reader.isSet(), "shouldn't be null");
1256+
reader.setPosition(0);
1257+
reader.next();
1258+
FieldReader uuidReader = reader.reader();
1259+
UuidHolder holder = new UuidHolder();
1260+
uuidReader.read(holder);
1261+
ByteBuffer bb = ByteBuffer.wrap(holder.value);
1262+
UUID actualUuid = new UUID(bb.getLong(), bb.getLong());
1263+
assertEquals(u1, actualUuid);
1264+
reader.next();
1265+
uuidReader = reader.reader();
1266+
uuidReader.read(holder);
1267+
bb = ByteBuffer.wrap(holder.value);
1268+
actualUuid = new UUID(bb.getLong(), bb.getLong());
1269+
assertEquals(u2, actualUuid);
1270+
}
1271+
}
1272+
12011273
private void writeIntValues(UnionListWriter writer, int[] values) {
12021274
writer.startList();
12031275
for (int v : values) {

java/vector/src/test/java/org/apache/arrow/vector/UuidVector.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import java.util.UUID;
2121
import org.apache.arrow.memory.BufferAllocator;
2222
import org.apache.arrow.memory.util.hash.ArrowBufHasher;
23+
import org.apache.arrow.vector.complex.impl.UuidReaderImpl;
24+
import org.apache.arrow.vector.complex.reader.FieldReader;
25+
import org.apache.arrow.vector.holder.UuidHolder;
2326
import org.apache.arrow.vector.types.pojo.Field;
2427
import org.apache.arrow.vector.types.pojo.FieldType;
2528
import org.apache.arrow.vector.types.pojo.UuidType;
@@ -79,11 +82,21 @@ public TransferPair makeTransferPair(ValueVector to) {
7982
return new TransferImpl((UuidVector) to);
8083
}
8184

85+
@Override
86+
protected FieldReader getReaderImpl() {
87+
return new UuidReaderImpl(this);
88+
}
89+
8290
public void setSafe(int index, byte[] value) {
8391
getUnderlyingVector().setIndexDefined(index);
8492
getUnderlyingVector().setSafe(index, value);
8593
}
8694

95+
public void get(int index, UuidHolder holder) {
96+
holder.value = getUnderlyingVector().get(index);
97+
holder.isSet = 1;
98+
}
99+
87100
public class TransferImpl implements TransferPair {
88101
UuidVector to;
89102
ValueVector targetUnderlyingVector;

0 commit comments

Comments
 (0)