diff --git a/java/c/src/main/java/org/apache/arrow/c/Data.java b/java/c/src/main/java/org/apache/arrow/c/Data.java
index 9ee5a6c757c..23cd48c1317 100644
--- a/java/c/src/main/java/org/apache/arrow/c/Data.java
+++ b/java/c/src/main/java/org/apache/arrow/c/Data.java
@@ -28,6 +28,7 @@
import org.apache.arrow.vector.dictionary.DictionaryProvider;
import org.apache.arrow.vector.ipc.ArrowReader;
import org.apache.arrow.vector.ipc.message.ArrowRecordBatch;
+import org.apache.arrow.vector.table.Table;
import org.apache.arrow.vector.types.pojo.ArrowType;
import org.apache.arrow.vector.types.pojo.ArrowType.ArrowTypeID;
import org.apache.arrow.vector.types.pojo.Field;
@@ -114,6 +115,60 @@ public static void exportVector(BufferAllocator allocator, FieldVector vector, D
exporter.export(out, vector, provider);
}
+ /**
+ * Export the current contents of a Java Table using the C data
+ * interface format.
+ *
+ * The table is exported as if it were a struct array. The
+ * resulting ArrowArray struct keeps the record batch data and buffers alive
+ * until its release callback is called by the consumer.
+ *
+ * @param allocator Buffer allocator for allocating C data interface fields
+ * @param table Table to export
+ * @param out C struct where to export the record batch
+ */
+ public static void exportTable(BufferAllocator allocator, Table table, ArrowArray out) {
+ exportTable(allocator, table, table.getDictionaryProvider(), out, null);
+ }
+
+ /**
+ * Export the current contents of a Java Table using the C data
+ * interface format.
+ *
+ * The table is exported as if it were a struct array. The
+ * resulting ArrowArray struct keeps the record batch data and buffers alive
+ * until its release callback is called by the consumer.
+ *
+ * @param allocator Buffer allocator for allocating C data interface fields
+ * @param table Table to export
+ * @param provider Dictionary provider for dictionary encoded vectors
+ * (optional)
+ * @param out C struct where to export the record batch
+ */
+ public static void exportTable(BufferAllocator allocator, Table table,
+ DictionaryProvider provider, ArrowArray out) {
+ exportTable(allocator, table, provider, out, null);
+ }
+
+ /**
+ * Export the current contents of a Java Table using the C data interface format.
+ *
+ * The table is exported as if it were a struct array. The
+ * resulting ArrowArray struct keeps the record batch data and buffers alive
+ * until its release callback is called by the consumer.
+ *
+ * @param allocator Buffer allocator for allocating C data interface fields
+ * @param table Table to export
+ * @param provider Dictionary provider for dictionary encoded vectors
+ * (optional)
+ * @param out C struct where to export the record batch
+ * @param outSchema C struct where to export the record batch schema (optional)
+ */
+ public static void exportTable(BufferAllocator allocator, Table table,
+ DictionaryProvider provider, ArrowArray out, ArrowSchema outSchema) {
+ exportVectorSchemaRoot(allocator, table.toVectorSchemaRoot(), provider, out, outSchema);
+ }
+
/**
* Export the current contents of a Java VectorSchemaRoot using the C data
* interface format.
@@ -121,7 +176,7 @@ public static void exportVector(BufferAllocator allocator, FieldVector vector, D
* The vector schema root is exported as if it were a struct array. The
* resulting ArrowArray struct keeps the record batch data and buffers alive
* until its release callback is called by the consumer.
- *
+ *
* @param allocator Buffer allocator for allocating C data interface fields
* @param vsr Vector schema root to export
* @param provider Dictionary provider for dictionary encoded vectors
@@ -129,7 +184,7 @@ public static void exportVector(BufferAllocator allocator, FieldVector vector, D
* @param out C struct where to export the record batch
*/
public static void exportVectorSchemaRoot(BufferAllocator allocator, VectorSchemaRoot vsr,
- DictionaryProvider provider, ArrowArray out) {
+ DictionaryProvider provider, ArrowArray out) {
exportVectorSchemaRoot(allocator, vsr, provider, out, null);
}
diff --git a/java/c/src/test/java/org/apache/arrow/c/RoundtripTest.java b/java/c/src/test/java/org/apache/arrow/c/RoundtripTest.java
index fb7714fac0b..61f26768acd 100644
--- a/java/c/src/test/java/org/apache/arrow/c/RoundtripTest.java
+++ b/java/c/src/test/java/org/apache/arrow/c/RoundtripTest.java
@@ -90,6 +90,7 @@
import org.apache.arrow.vector.holders.IntervalDayHolder;
import org.apache.arrow.vector.holders.NullableLargeVarBinaryHolder;
import org.apache.arrow.vector.holders.NullableUInt4Holder;
+import org.apache.arrow.vector.table.Table;
import org.apache.arrow.vector.types.TimeUnit;
import org.apache.arrow.vector.types.Types.MinorType;
import org.apache.arrow.vector.types.pojo.ArrowType;
@@ -657,6 +658,39 @@ public void testVectorSchemaRoot() {
imported.close();
}
+ /**
+ * Tests exporting Table and importing back to VSR. Importing back to Table is not supported at present.
+ */
+ @Test
+ public void testTable() {
+ VectorSchemaRoot imported;
+
+ // Consumer allocates empty structures
+ try (ArrowSchema consumerArrowSchema = ArrowSchema.allocateNew(allocator);
+ ArrowArray consumerArrowArray = ArrowArray.allocateNew(allocator)) {
+ try (
+ VectorSchemaRoot vsr = createTestVSR();
+ Table table = new Table(vsr);
+ ) {
+ // Producer creates structures from existing memory pointers
+ try (ArrowSchema arrowSchema = ArrowSchema.wrap(consumerArrowSchema.memoryAddress());
+ ArrowArray arrowArray = ArrowArray.wrap(consumerArrowArray.memoryAddress())) {
+ // Producer exports vector into the C Data Interface structures
+ Data.exportTable(allocator, table, arrowArray);
+ }
+ }
+ // Consumer imports vector
+ imported = Data.importVectorSchemaRoot(allocator, consumerArrowArray, consumerArrowSchema, null);
+ }
+
+ // Ensure that imported VectorSchemaRoot is valid even after C Data Interface
+ // structures are closed
+ try (VectorSchemaRoot original = createTestVSR()) {
+ assertTrue(imported.equals(original));
+ }
+ imported.close();
+ }
+
@Test
public void testVectorSchemaRootWithDuplicatedFieldNames() {
VectorSchemaRoot imported;
diff --git a/java/pom.xml b/java/pom.xml
index cdd8fa181de..0438bb8fda8 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -303,9 +303,9 @@
8.19
- org.slf4j
- jcl-over-slf4j
- 1.7.5
+ org.slf4j
+ jcl-over-slf4j
+ 1.7.5
@@ -749,7 +749,7 @@
shade-flatbuffers
- shade-format-flatbuffers
+ shade-format-flatbuffers
@@ -763,7 +763,7 @@
1.8
- !m2e.version
+ !m2e.version
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/table/BaseTable.java b/java/vector/src/main/java/org/apache/arrow/vector/table/BaseTable.java
new file mode 100644
index 00000000000..b405782c777
--- /dev/null
+++ b/java/vector/src/main/java/org/apache/arrow/vector/table/BaseTable.java
@@ -0,0 +1,387 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.arrow.vector.table;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.arrow.util.AutoCloseables;
+import org.apache.arrow.util.Preconditions;
+import org.apache.arrow.vector.FieldVector;
+import org.apache.arrow.vector.ValueVector;
+import org.apache.arrow.vector.VectorSchemaRoot;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.dictionary.Dictionary;
+import org.apache.arrow.vector.dictionary.DictionaryEncoder;
+import org.apache.arrow.vector.dictionary.DictionaryProvider;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.Schema;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * Abstract base class for Table.
+ *
+ * This API is EXPERIMENTAL.
+ */
+public abstract class BaseTable implements AutoCloseable {
+
+ /** The field vectors holding the data in this table. */
+ protected final List fieldVectors;
+
+ /**
+ * An optional DictionaryProvider. One must be present if any vector in the table is dictionary
+ * encoded.
+ */
+ protected DictionaryProvider dictionaryProvider;
+
+ /** A map of Fields to FieldVectors used to select Fields. */
+ protected final Map fieldVectorsMap = new LinkedHashMap<>();
+
+ /** The schema for the table. */
+ protected Schema schema;
+
+ /** The number of rows of data in the table; not necessarily the same as the table row capacity. */
+ protected int rowCount;
+
+ /**
+ * Constructs new instance with the given rowCount, and containing the schema and each of the
+ * given vectors.
+ *
+ * @param fieldVectors the FieldVectors containing the table's data
+ * @param rowCount the number of rows in the table
+ * @param provider a dictionary provider, may be null if none of the vectors in the table are
+ * encoded
+ */
+ public BaseTable(List fieldVectors, int rowCount, DictionaryProvider provider) {
+
+ this.dictionaryProvider = provider;
+ this.rowCount = rowCount;
+ this.fieldVectors = new ArrayList<>();
+ List fields = new ArrayList<>();
+ for (FieldVector fv : fieldVectors) {
+ TransferPair transferPair = fv.getTransferPair(fv.getAllocator());
+ transferPair.transfer();
+ FieldVector newVector = (FieldVector) transferPair.getTo();
+ newVector.setValueCount(rowCount);
+
+ Field newField = newVector.getField();
+ this.fieldVectors.add(newVector);
+ fields.add(newField);
+ fieldVectorsMap.put(newField, newVector);
+ }
+ this.schema = new Schema(fields);
+ }
+
+ /**
+ * Returns a FieldReader for the vector with the given name.
+ *
+ * @param name The name of a vector in this Table (case-sensitive)
+ * @return A FieldReader for the named FieldVector
+ */
+ public FieldReader getReader(String name) {
+ for (Map.Entry entry : fieldVectorsMap.entrySet()) {
+ if (entry.getKey().getName().equals(name)) {
+ return entry.getValue().getReader();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a FieldReader for the given field.
+ *
+ * @param field The field to be read
+ * @return A FieldReader for the given field
+ */
+ public FieldReader getReader(Field field) {
+ return fieldVectorsMap.get(field).getReader();
+ }
+
+ /**
+ * Returns a FieldReader for the field at the given vector index.
+ *
+ * @param index The 0-based index of the field desired.
+ * @return A FieldReader for the requested field
+ */
+ public FieldReader getReader(int index) {
+ Preconditions.checkArgument(index >= 0 && index < fieldVectors.size());
+ return fieldVectors.get(index).getReader();
+ }
+
+ /**
+ * Returns the schema for this Table.
+ */
+ public Schema getSchema() {
+ return schema;
+ }
+
+ /**
+ * Returns the Field with the given name if one exists in this table.
+ *
+ * @param fieldName the name of the field to return
+ * @return a field with the given name if one is present
+ * @throws IllegalArgumentException – if the field was not found
+ */
+ public Field getField(String fieldName) {
+ return getSchema().findField(fieldName);
+ }
+
+ /**
+ * Returns a list of Field created by adding the given vector to the vectors in this Table.
+ *
+ * @param index field index
+ * @param vector vector to be added.
+ * @return out List of FieldVectors with vector added
+ */
+ List insertVector(int index, FieldVector vector) {
+ Preconditions.checkNotNull(vector);
+ Preconditions.checkArgument(index >= 0 && index <= fieldVectors.size());
+ List newVectors = new ArrayList<>();
+ if (index == fieldVectors.size()) {
+ newVectors.addAll(fieldVectors);
+ newVectors.add(vector);
+ } else {
+ for (int i = 0; i < fieldVectors.size(); i++) {
+ if (i == index) {
+ newVectors.add(vector);
+ }
+ newVectors.add(fieldVectors.get(i));
+ }
+ }
+ return newVectors;
+ }
+
+ /**
+ * Returns a new List of FieldVectors created by removing the selected Vector from the list in
+ * this Table.
+ *
+ * @param index field index
+ * @return out List of FieldVectors like the list in this table, but with the argument removed
+ */
+ List extractVector(int index) {
+ Preconditions.checkArgument(index >= 0 && index < fieldVectors.size());
+ List newVectors = new ArrayList<>();
+ for (int i = 0; i < fieldVectors.size(); i++) {
+ if (i != index) {
+ newVectors.add(fieldVectors.get(i));
+ }
+ }
+ return newVectors;
+ }
+
+ /** Returns the number of vectors (columns) in this table. */
+ public int getVectorCount() {
+ return fieldVectors.size();
+ }
+
+ /**
+ * Closes all the vectors holding data for this table and sets the rowcount to 0, preventing
+ * enumeration.
+ */
+ void clear() {
+ close();
+ rowCount = 0;
+ }
+
+ /** Closes all the vectors holding data for this table. */
+ @Override
+ public void close() {
+ try {
+ AutoCloseables.close(fieldVectors);
+ } catch (RuntimeException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ // should never happen since FieldVector.close() doesn't throw IOException
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /** Returns the number of rows in this table. */
+ public long getRowCount() {
+ return rowCount;
+ }
+
+ /**
+ * Returns a new VectorSchemaRoot with the data and schema from this table. Data is transferred to
+ * the new VectorSchemaRoot, so this table is cleared and the rowCount is set to 0;
+ *
+ * @return a new VectorSchemaRoot
+ */
+ public VectorSchemaRoot toVectorSchemaRoot() {
+ VectorSchemaRoot vsr =
+ new VectorSchemaRoot(
+ fieldVectors.stream()
+ .map(
+ v -> {
+ TransferPair transferPair = v.getTransferPair(v.getAllocator());
+ transferPair.transfer();
+ return (FieldVector) transferPair.getTo();
+ })
+ .collect(Collectors.toList()));
+ clear();
+ return vsr;
+ }
+
+ /**
+ * Returns the vector with the given name, or throws IllegalArgumentException if the name is not found. Names are
+ * case-sensitive.
+ *
+ * @param columnName The name of the vector
+ * @return the Vector with the given name, or null
+ * @throws IllegalArgumentException if the name is not the name of a vector in the table.
+ */
+ FieldVector getVector(String columnName) {
+ for (Map.Entry entry : fieldVectorsMap.entrySet()) {
+ if (entry.getKey().getName().equals(columnName)) {
+ return entry.getValue();
+ }
+ }
+ throw new IllegalStateException(String.format("No vector named '%s' is present in the table", columnName));
+ }
+
+ /**
+ * Returns the vector at the given position.
+ *
+ * @param columnIndex The 0-based position of the vector
+ */
+ FieldVector getVector(int columnIndex) {
+ return fieldVectors.get(columnIndex);
+ }
+
+ /**
+ * Returns an immutable Row object holding a reference to this table. The default character
+ * encoding used by the cursor to decode Strings will be StandardCharsets.UTF_8 as this is the only charset
+ * supported in Arrow format.
+ */
+ public Row immutableRow() {
+ return new Row(this);
+ }
+
+ /**
+ * Returns a tab separated value of vectors (based on their java object representation).
+ */
+ public String contentToTSVString() {
+ StringBuilder sb = new StringBuilder();
+ List row = new ArrayList<>(schema.getFields().size());
+ for (Field field : schema.getFields()) {
+ row.add(field.getName());
+ }
+ printRow(sb, row);
+ for (int i = 0; i < rowCount; i++) {
+ row.clear();
+ for (FieldVector v : fieldVectors) {
+ row.add(v.getObject(i));
+ }
+ printRow(sb, row);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Prints a single row without a header to the given StringBuilder.
+ *
+ * @param sb the StringBuilder to write to
+ * @param row the row to write
+ */
+ private void printRow(StringBuilder sb, List row) {
+ boolean first = true;
+ for (Object v : row) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append("\t");
+ }
+ sb.append(v);
+ }
+ sb.append("\n");
+ }
+
+ /**
+ * Returns true if the row at the given index has been deleted and false otherwise.
+ *
+ * If the index is larger than the number of rows, the method returns true.
+ *
+ * @param rowNumber The 0-based index of the possibly deleted row
+ * @return true if the row at the index was deleted; false otherwise
+ */
+ public boolean isRowDeleted(int rowNumber) {
+ return false;
+ }
+
+ /** Returns the DictionaryProvider for this table. It can be used to decode an encoded values */
+ public DictionaryProvider getDictionaryProvider() {
+ return dictionaryProvider;
+ }
+
+ /**
+ * Returns a ValueVector containing the decoded version of the vector with the given name.
+ * @param vectorName The name of the vector to decode
+ * @param dictionaryId The identifier for the dictionary to use when decoding. Must match the id returned by the
+ * dictionary's getId() method.
+ * @return A ValueVector
+ */
+ public ValueVector decode(String vectorName, long dictionaryId) {
+ Dictionary dictionary = getDictionary(dictionaryId);
+
+ FieldVector vector = getVector(vectorName);
+ if (vector == null) {
+ throw new IllegalArgumentException(
+ String.format("No vector with name '%s' is present in table", vectorName));
+ }
+
+ DictionaryEncoder decoder = new DictionaryEncoder(dictionary, vector.getAllocator());
+ return decoder.decode(vector);
+ }
+
+ /**
+ * Returns a ValueVector containing the encoded version of the vector with the given name.
+ * @param vectorName The name of the vector to encode
+ * @param dictionaryId The identifier for the dictionary to use when encoding. Must match the id returned by the
+ * dictionary's getId() method.
+ * @return A ValueVector
+ */
+ public ValueVector encode(String vectorName, long dictionaryId) {
+ Dictionary dictionary = getDictionary(dictionaryId);
+ FieldVector vector = getVector(vectorName);
+ if (vector == null) {
+ throw new IllegalArgumentException(
+ String.format("No vector with name '%s' is present in table", vectorName));
+ }
+ DictionaryEncoder decoder = new DictionaryEncoder(dictionary, vector.getAllocator());
+ return decoder.encode(vector);
+ }
+
+ /**
+ * Returns the dictionary with given id.
+ * @param dictionaryId A long integer that is the id returned by the dictionary's getId() method
+ */
+ private Dictionary getDictionary(long dictionaryId) {
+ if (dictionaryProvider == null) {
+ throw new IllegalStateException("No dictionary provider is present in table.");
+ }
+
+ Dictionary dictionary = dictionaryProvider.lookup(dictionaryId);
+ if (dictionary == null) {
+ throw new IllegalArgumentException("No dictionary with id '%n' exists in the table");
+ }
+ return dictionary;
+ }
+}
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/table/README.md b/java/vector/src/main/java/org/apache/arrow/vector/table/README.md
new file mode 100644
index 00000000000..032095f355b
--- /dev/null
+++ b/java/vector/src/main/java/org/apache/arrow/vector/table/README.md
@@ -0,0 +1,375 @@
+
+
+# Table
+
+**NOTE**: The API is experimental and subject to change. See the list of limitations below.
+
+*Table* is a new immutable tabular data structure based on FieldVectors. A mutable version (*MutableTable*) is expected in a subsequent release. This document describes the Table API.
+
+---
+
+Like VectorSchemaRoot, *Table* is a columnar data structure backed by Arrow arrays, or more specifically, by FieldVector objects. It differs from VectorSchemaRoot mainly in that it is fully immutable and lacks support for batch operations. Anyone processing batches of tabular data in a pipeline should continue to use VectorSchemaRoot.
+
+## Mutation in Table and VectorSchemaRoot
+
+VectorSchemaRoot provides a thin wrapper on the FieldVectors that hold its data. Individual FieldVectors can be retrieved from the VectorSchemaRoot. These FieldVectors have *setters* for modifying their elements, so VectorSchemaRoot is immutable only by convention. The protocol for mutating a vector is documented in the ValueVector class:
+
+- values need to be written in order (e.g. index 0, 1, 2, 5)
+- null vectors start with all values as null before writing anything
+- for variable width types, the offset vector should be all zeros before writing
+- you must call setValueCount before a vector can be read
+- you should never write to a vector once it has been read.
+
+The rules aren't enforced by the API so the programmer is responsible for ensuring that they are followed. Failure to do so could lead to runtime exceptions.
+
+_Table_, on the other hand, is immutable. The underlying vectors are not exposed. When a Table is created from existing vectors, their memory is transferred to new vectors, so subsequent changes to the original vectors can't impact the new table's values.
+
+## Features and limitations
+
+### Features
+A basic set of table functionality is included in this release:
+
+- Create a Table from FieldVectors or VectorSchemaRoot
+- Iterate tables by row or set the current row index directly
+- Access Vector values as primitives, objects, and/or NullableHolders (depending on type)
+- Get FieldReader for any vector
+- Add and remove FieldVectors
+- Encode and decode a table's vectors using DictionaryEncoding
+- Export Table memory for use by native code
+- Print first rows to Strings
+- Get table schema
+- Slice tables
+- Convert table to VectorSchemaRoot
+
+### Limitations
+The following are the major limitations of v. 10.0.0 release:
+
+1. **Creating Tables with data imported using the C-Data API will result in a runtime exception**. Support for ths feature is gated on PR#13248 (https://github.com/apache/arrow/pull/13248).
+2. No support ChunkedArrays or any form of row-group. Support for ChunkedArrows or row groups will be considered for a future release.
+3. No support for native interface using the C-Stream API. Support for the streaming API will be delivered with or after Item 1.
+4. No support for creating tables directly from Java POJOs. All data held by a table must be imported via a VectorSchemaRoot, or from collections or arrays of FieldVectors.
+5. No support for mutable tables.
+
+## What's in a Table?
+
+Like VectorSchemaRoot, Table consists of a `Schema` and an ordered collection of `FieldVector` objects, but it is designed to be accessed via a row-oriented interface.
+
+## Table API: Creating Tables
+
+### Creating a Table from a VectorSchemaRoot
+
+Tables are created from a VectorSchemaRoot as shown below. The memory buffers holding the data are transferred from the VectorSchemaRoot to new vectors in the new Table, clearing the original VectorSchemaRoot in the process. This ensures that the data in your new Table is never changed. Since the buffers are transferred rather than copied, this is a very low overhead operation.
+
+```java
+ VectorSchemaRoot vsr = getMyVsr();
+ Table t = new Table(vsr);
+```
+
+If you now update the FieldVectors used to create the VectorSchemaRoot (using some variation of `ValueVector#setSafe()`), the VectorSchemaRoot *vsr* would reflect those changes, but the values in Table *t* are unchanged.
+
+***Current Limitation:*** Due to an unresolved limitation in `CDataReferenceManager`, you cannot currently create a Table from a VectorSchemaRoot that was created in native code and transferred to Java via the C-Data Interface.
+
+### Creating a Table from ValueVectors
+
+Tables can be created from ValueVectors as shown below.
+
+```java
+ IntVector myVector = createMyIntVector();
+ VectorSchemaRoot vsr1 = new VectorSchemaRoot(myVector);
+```
+
+or
+
+```java
+ IntVector myVector = createMyIntVector();
+ List fvList = List.of(myVector);
+ VectorSchemaRoot vsr1 = new VectorSchemaRoot(fvList);
+```
+
+It is rarely a good idea to share vectors between multiple VectorSchemaRoots, and it would not be a good idea to share them between VectorSchemaRoots and tables. Creating a VectorSchemaRoot from a list of vectors does not cause the reference counts for the vectors to be incremented. Unless you manage the counts manually, the code shown below would lead to more references to the vectors than reference counts, and that could lead to trouble. There is an implicit assumption that the vectors were created for use by *one* VectorSchemaRoot that this code violates.
+
+*Don't do this:*
+
+```Java
+ IntVector myVector = createMyIntVector(); // Reference count for myVector = 1
+ VectorSchemaRoot vsr1 = new VectorSchemaRoot(myVector); // Still one reference
+ VectorSchemaRoot vsr2 = new VectorSchemaRoot(myVector);
+ // Ref count is still one, but there are two VSRs with a reference to myVector
+ vsr2.clear(); // Reference count for myVector is 0.
+```
+
+What is happening is that the reference counter works at a lower level than the VectorSchemaRoot interface. A reference counter counts references to ArrowBuf instances that control memory buffers. It doesn't count references to the ValueVectors that hold *them*. In the example above, each ArrowBuf is held by one ValueVector, so there is only one reference. This distinction is blurred though, when you call the VectorSchemaRoot's clear() method, which frees the memory held by each of the vectors it references even though another instance might refer to the same vectors.
+
+When you create Tables from vectors, it's assumed that there are no external references to those vectors. But, just to be on the safe side, the buffers underlying these vectors are transferred to new ValueVectors in the new Table, and the original vectors are cleared.
+
+*Don't do this either, but note the difference from above:*
+
+```Java
+ IntVector myVector = createMyIntVector(); // Reference count for myVector = 1
+ Table t1 = new Table(myVector); // myVector is cleared; Table t1 has a new hidden vector with
+ // the data from myVector
+ Table t2 = new Table(myVector); // t2 has no rows because the myVector was just cleared
+ // t1 continues to have the data from the original vector
+ t2.clear(); // no change because t2 is already empty and t1 is independent
+```
+
+With Tables, memory is explicitly transferred on instantiatlon so the buffers are held by that table are held by *only* that table.
+
+#### Creating Tables with dictionary-encoded vectors
+
+***Note: this section is highly speculative***
+
+Another point of difference is that dictionary-encoding is managed separately from VectorSchemaRoot, while Tables hold an optional DictionaryProvider instance. If any vectors in the source data are encoded, a DictionaryProvider must be set to un-encode the values.
+
+```java
+ VectorSchemaRoot vsr = myVsr();
+ DictionaryProvider provider = myProvider();
+ Table t = new Table(vsr, provider);
+```
+
+In the immutable Table case, dictionaries are used in a way that's similar to the approach used with ValueVectors. To decode a vector, the user provides the dictionary id and the name of the vector to decode:
+
+```Java
+ Table t = new Table(vsr, provider);
+ ValueVector decodedName = t.decode("name", 1L);
+```
+
+To encode a vector from a table, a similar approach is used:
+
+```Java
+ Table t = new Table(vsr, provider);
+ ValueVector encodedName = t.encode("name", 1L);
+```
+
+```java
+ String output = myTable.contentToTSVString(true);
+```
+
+### Freeing memory explicitly
+
+Tables use off-heap memory that must be freed when it is no longer needed. Table implements AutoCloseable so the best way to create one is in a try-with-resources block:
+
+```java
+ try (VectorSchemaRoot vsr = myMethodForGettingVsrs();
+ Table t = new Table(vsr)) {
+ // do useful things.
+ }
+```
+
+If you don't use a try-with-resources block, you must close the Table manually:
+
+````java
+ try {
+ VectorSchemaRoot vsr = myMethodForGettingVsrs();
+ Table t = new Table(vsr);
+ // do useful things.
+ } finally {
+ vsr.close();
+ t.close();
+ }
+````
+
+Manually closing should be performed in a finally block.
+
+## Table API: getting the schema
+
+You get the table's schema the same way you do with a VectorSchemaRoot:
+
+```java
+ Schema s = table.getSchema();
+```
+
+## Table API: Adding and removing vectors
+
+Table provides facilities for adding and removing FieldVectors modeled on the same functionality in VectorSchemaRoot. As with VectorSchemaRoot, these operations return new instances rather than modifiying the original instance in-place.
+
+```java
+ try (Table t = new Table(vectorList)) {
+ IntVector v3 = new IntVector("3", intFieldType, allocator);
+ Table t2 = t.addVector(2, v3);
+ Table t3 = t2.removeVector(1);
+ // don't forget to close t2 and t3
+ }
+```
+
+## Table API: Slicing tables
+
+Table supports *slice()* operations, where a slice of a source table is a second Table that refers to a single, contiguous range of rows in the source.
+
+```Java
+ try (Table t = new Table(vectorList)) {
+ Table t2 = t.slice(100, 200); // creates a slice referencing the values in range (100, 200]
+ ...
+ }
+```
+
+If you created a slice with *all* the values in the source table (as shown below), how would that differ from a new Table constructed with the same vectors as the source?
+
+```Java
+ try (Table t = new Table(vectorList)) {
+ Table t2 = t.slice(0, t.getRowCount()); // creates a slice referencing all the values in t
+ // ...
+ }
+```
+
+The difference is that when you *construct* a new table, the buffers are transferred from the source vectors to new vectors in the destination. With a slice, both tables share the same underlying vectors. That's OK, though, since both Tables are immutable.
+
+Slices will not be supported in MutableTables.
+
+## Table API: Using FieldReaders
+
+You can get a FieldReader for any vector in the Table using either the Field, vector index, or vector name. The signatures are the same as in VectorSchemaRoot.
+
+```java
+ FieldReader nameReader = table.getReader("user_name");
+```
+
+## Table API: Row operations
+
+Row-based access is supported using a Row object. Row provides *get()* methods by both vector name and vector position, but no *set()* operations. It is important to recognize that it's NOT a reified row, but rather operates like a cursor where the data from numerous logical rows in the Table can be viewed (one row at a time) using the same Row instance. See "Getting around" below for information about how to navigate through the table.
+
+**Note**: A mutable row implementation is expected with the release of MutableTable, which will support both mutable and immutable Rows.
+
+### Getting a row
+
+Calling `immutableRow()` on any table instance returns a row supporting read operations.
+
+```java
+ Row r = table.immutableRow();
+```
+
+### Getting around
+
+Since rows are iterable, you can traverse a table using a standard while loop:
+
+```java
+ Row r = table.immutableRow();
+ while (r.hasNext()) {
+ r.next();
+ // do something useful here
+ }
+```
+
+Table implements `Iterable` so you can access rows directly from Table in an enhanced *for* loop:
+
+```java
+ for (Row row: table) {
+ int age = row.getInt("age");
+ boolean nameIsNull = row.isNull("name");
+ ...
+ }
+```
+
+Finally, while rows are usually iterated in the order of the underlying data vectors, but they are also positionable using the `Row#setPosition()` method, so you can skip to a specific row. Row numbers are 0-based.
+
+```java
+ Row r = table.immutableRow();
+ int age101 = r.setPosition(101); // change position directly to 101
+```
+
+Any changes to position are of course applied to all the columns in the table.
+
+Note that you must call `next()`, or `setPosition()` before accessing values via a row. Failure to do so results in a runtime exception.
+
+### Read operations using rows
+
+Methods are available for getting values by vector name and vector index, where index is the 0-based position of the vector in the table. For example, assuming 'age' is the 13th vector in 'table', the following two gets are equivalent:
+
+```java
+ Row r = table.immutableRow();
+ r.next(); // position the row at the first value
+ int age1 = r.get("age"); // gets the value of vector named 'age' in the table at row 0
+ int age2 = r.get(12); // gets the value of the 13th vecto in the table at row 0
+```
+
+You can also get value using a NullableHolder. For example:
+
+```Java
+
+ NullableIntHolder holder = new NullableIntHolder();
+ int b = row.getInt("age", holder);
+```
+
+This can be used to retrieve values without creating a new Object for each.
+
+In addition to getting values, you can check if a value is null using `isNull()` and you can get the current row number:
+
+```java
+ boolean name0isNull = row.isNull("name");
+ int row = row.getRowNumber();
+```
+
+Note that while there are getters for most vector types (e.g. *getInt()* for use with IntVector) and a generic *isNull()* method, there is no *getNull()* method for use with the NullVector type or *getZero()* for use with ZeroVector (a zero-length vector of any type).
+
+#### Reading values as Objects
+
+For any given vector type, the basic *get()* method returns a primitive value wherever possible. For example, *getTimeStampMicro()* returns a long value that encodes the timestamp. To get the LocalDateTime object representing that timestamp in Java, another method with 'Obj' appended to the name is provided. For example:
+
+```java
+ long ts = row.getTimeStampMicro();
+ LocalDateTime tsObject = row.getTimeStampMicroObj();
+```
+
+The exception to this naming scheme is for complex vector types (List, Map, Schema, Union, DenseUnion, and ExtensionType). These always return objects rather than primitives so no "Obj" extension is required. It is expected that some users may subclass Row to add getters that are more specific to their needs.
+
+#### Reading VarChars and LargeVarChars
+
+Strings in arrow are represented as byte arrays, encoded with the UTF-8 charset as this is the only character set supported in the Arrow format. You can get either a String result or the actual byte array.
+
+```Java
+ byte[] b = row.getVarChar("first_name");
+ String s = row.getVarCharObj("first_name"); // uses the default encoding (UTF-8)
+```
+
+## Table API: Converting a Table to a VectorSchemaRoot
+
+Tables can be converted to VectorSchemaRoot objects using the *toVectorSchemaRoot()* method.
+
+```java
+ VectorSchemaRoot root = myTable.toVectorSchemaRoot();
+```
+
+Buffers are transferred to the VectorSchemaRoot and the Table is cleared.
+
+## Table API: Working with the C-Data interface
+
+The ability to work with native code is required for many Arrow features. This section describes how tables can be be exported and imported.
+
+### Exporting Tables to native code
+
+This works by converting the data to a VectorSchemaRoot and using the existing facilities for transferring the data. This would not generally be ideal because conversion to a VectorSchemaRoot breaks the immutability guarantees. Using the static utility methods defined in the class org.apache.arrow.c.Data` avoids this concern because the vector schema root used is not expored. See the example code below:
+
+```java
+ Data.exportTable(bufferAllocator, table, dictionaryProvider, outArrowArray);
+```
+
+If the table contains dictionary-encoded vectors, it should have been created with a dictionary provider to support encode and decode operations. In that case, the provider argument can be ommitted and the table's provider attribute will be used:
+
+```java
+ Data.exportTable(bufferAllocator, table, outArrowArray);
+```
+
+### Importing Tables from native code
+
+***Current limitation: Data imported from native code using the C-Data-interface cannot be used in a table, because the current implementation of CDataReferenceManager does not support the transfer operation.***
+
+## Table API: Working with the C-Stream interface
+
+***Current limitation: Streaming API is not currently supported. Support is planned for a future release.***
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/table/Row.java b/java/vector/src/main/java/org/apache/arrow/vector/table/Row.java
new file mode 100644
index 00000000000..b6cc566f2f7
--- /dev/null
+++ b/java/vector/src/main/java/org/apache/arrow/vector/table/Row.java
@@ -0,0 +1,1852 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.arrow.vector.table;
+
+import java.math.BigDecimal;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.time.Period;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.vector.BigIntVector;
+import org.apache.arrow.vector.BitVector;
+import org.apache.arrow.vector.DecimalVector;
+import org.apache.arrow.vector.DurationVector;
+import org.apache.arrow.vector.FieldVector;
+import org.apache.arrow.vector.FixedSizeBinaryVector;
+import org.apache.arrow.vector.Float4Vector;
+import org.apache.arrow.vector.Float8Vector;
+import org.apache.arrow.vector.IntVector;
+import org.apache.arrow.vector.IntervalDayVector;
+import org.apache.arrow.vector.IntervalMonthDayNanoVector;
+import org.apache.arrow.vector.IntervalYearVector;
+import org.apache.arrow.vector.LargeVarBinaryVector;
+import org.apache.arrow.vector.LargeVarCharVector;
+import org.apache.arrow.vector.PeriodDuration;
+import org.apache.arrow.vector.SmallIntVector;
+import org.apache.arrow.vector.TimeMicroVector;
+import org.apache.arrow.vector.TimeMilliVector;
+import org.apache.arrow.vector.TimeNanoVector;
+import org.apache.arrow.vector.TimeSecVector;
+import org.apache.arrow.vector.TimeStampMicroTZVector;
+import org.apache.arrow.vector.TimeStampMicroVector;
+import org.apache.arrow.vector.TimeStampMilliTZVector;
+import org.apache.arrow.vector.TimeStampMilliVector;
+import org.apache.arrow.vector.TimeStampNanoTZVector;
+import org.apache.arrow.vector.TimeStampNanoVector;
+import org.apache.arrow.vector.TimeStampSecTZVector;
+import org.apache.arrow.vector.TimeStampSecVector;
+import org.apache.arrow.vector.TinyIntVector;
+import org.apache.arrow.vector.UInt1Vector;
+import org.apache.arrow.vector.UInt2Vector;
+import org.apache.arrow.vector.UInt4Vector;
+import org.apache.arrow.vector.UInt8Vector;
+import org.apache.arrow.vector.ValueVector;
+import org.apache.arrow.vector.VarBinaryVector;
+import org.apache.arrow.vector.VarCharVector;
+import org.apache.arrow.vector.complex.DenseUnionVector;
+import org.apache.arrow.vector.complex.ListVector;
+import org.apache.arrow.vector.complex.StructVector;
+import org.apache.arrow.vector.complex.UnionVector;
+import org.apache.arrow.vector.holders.NullableBigIntHolder;
+import org.apache.arrow.vector.holders.NullableBitHolder;
+import org.apache.arrow.vector.holders.NullableDecimalHolder;
+import org.apache.arrow.vector.holders.NullableDurationHolder;
+import org.apache.arrow.vector.holders.NullableFloat4Holder;
+import org.apache.arrow.vector.holders.NullableFloat8Holder;
+import org.apache.arrow.vector.holders.NullableIntHolder;
+import org.apache.arrow.vector.holders.NullableIntervalDayHolder;
+import org.apache.arrow.vector.holders.NullableIntervalMonthDayNanoHolder;
+import org.apache.arrow.vector.holders.NullableIntervalYearHolder;
+import org.apache.arrow.vector.holders.NullableSmallIntHolder;
+import org.apache.arrow.vector.holders.NullableTimeMicroHolder;
+import org.apache.arrow.vector.holders.NullableTimeMilliHolder;
+import org.apache.arrow.vector.holders.NullableTimeNanoHolder;
+import org.apache.arrow.vector.holders.NullableTimeSecHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampMicroHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampMicroTZHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampMilliHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampMilliTZHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampNanoHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampNanoTZHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampSecHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampSecTZHolder;
+import org.apache.arrow.vector.holders.NullableTinyIntHolder;
+import org.apache.arrow.vector.holders.NullableUInt1Holder;
+import org.apache.arrow.vector.holders.NullableUInt2Holder;
+import org.apache.arrow.vector.holders.NullableUInt4Holder;
+import org.apache.arrow.vector.holders.NullableUInt8Holder;
+
+/**
+ * Row is a positionable, immutable cursor backed by a {@link Table}.
+ *
+ * Getters are provided for most vector types. The exceptions being {@link org.apache.arrow.vector.NullVector},
+ * which only contains null values and has no getter, and {@link org.apache.arrow.vector.ZeroVector},
+ * which is a zero-length vector of any type
+ *
+ *
+ * This API is EXPERIMENTAL.
+ */
+public class Row implements Iterator {
+
+ /**
+ * Returns the standard character set to use for decoding strings. The Arrow format only supports UTF-8.
+ */
+ private static final Charset DEFAULT_CHARACTER_SET = StandardCharsets.UTF_8;
+
+ /** The table we're enumerating. */
+ protected final BaseTable table;
+ /** the current row number. */
+ protected int rowNumber = -1;
+ /** Indicates whether the next non-deleted row has been determined yet. */
+ private boolean nextRowSet;
+
+ /**
+ * An iterator that returns every row in the table, deleted or not. The implemented next() and
+ * hasNext() methods in Row wrap it with a filter to get only the non-deleted ones.
+ */
+ private final Iterator iterator = intIterator();
+
+ /**
+ * Constructs a new Row backed by the given table.
+ *
+ * @param table the table that this Row object represents
+ */
+ public Row(BaseTable table) {
+ this.table = table;
+ }
+
+ /**
+ * Resets the current row to -1 and returns this object.
+ */
+ public Row resetPosition() {
+ rowNumber = -1;
+ return this;
+ }
+
+ /**
+ * Moves this Row to the given 0-based row index.
+ *
+ * @return this Row for chaining
+ */
+ public Row setPosition(int rowNumber) {
+ this.rowNumber = rowNumber;
+ this.nextRowSet = false;
+ return this;
+ }
+
+ /**
+ * For vectors other than Union and DenseUnion, returns true if the value at columnName is null,
+ * and false otherwise.
+ *
+ * UnionVector#isNull always returns false, but the underlying vector may hold null values.
+ */
+ public boolean isNull(String columnName) {
+ ValueVector vector = table.getVector(columnName);
+ return vector.isNull(rowNumber);
+ }
+
+ /**
+ * For vectors other than Union and DenseUnion, returns true if the value at columnIndex is null,
+ * and false otherwise.
+ *
+ *
UnionVector#isNull always returns false, but the underlying vector may hold null values.
+ */
+ public boolean isNull(int columnIndex) {
+ ValueVector vector = table.getVector(columnIndex);
+ return vector.isNull(rowNumber);
+ }
+
+ /**
+ * Returns an object representing the value in the ExtensionTypeVector at the currentRow and vectorIndex. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if the type is incorrect.
+ */
+ public Object getExtensionType(int vectorIndex) {
+ FieldVector vector = table.getVector(vectorIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an object representing the value in the named ExtensionTypeVector at the currentRow. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type.
+ *
+ * @param columnName The name of the vector providing the result
+ * @return The object in the named column at the current row
+ */
+ public Object getExtensionType(String columnName) {
+ FieldVector vector = table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a Map from the column of the given vectorIndex at the current row. An IllegalStateException is
+ * thrown if the column is not present in the Row and a ClassCastException is thrown if
+ * it has a different type.
+ */
+ public List> getMap(int vectorIndex) {
+ ListVector vector = (ListVector) table.getVector(vectorIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a Map from the column of the given name at the current row. An IllegalStateException is
+ * thrown if the column is not present in the Row and a ClassCastException is thrown if
+ * it has a different type
+ */
+ public List> getMap(String columnName) {
+ ListVector vector = (ListVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an Object from the column at vectorIndex at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ */
+ public Object getStruct(int vectorIndex) {
+ StructVector vector = (StructVector) table.getVector(vectorIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an Object from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ */
+ public Object getStruct(String columnName) {
+ StructVector vector = (StructVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an Object from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ */
+ public Object getUnion(int vectorIndex) {
+ UnionVector vector = (UnionVector) table.getVector(vectorIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an Object from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ */
+ public Object getUnion(String columnName) {
+ UnionVector vector = (UnionVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an Object from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ */
+ public Object getDenseUnion(String columnName) {
+ DenseUnionVector vector = (DenseUnionVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an Object from the column with the given vectorIndex at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ */
+ public Object getDenseUnion(int vectorIndex) {
+ DenseUnionVector vector = (DenseUnionVector) table.getVector(vectorIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a List from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present in the Row and a ClassCastException is thrown
+ * if it has a different type
+ */
+ public List> getList(String columnName) {
+ ListVector vector = (ListVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a List from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present and a ClassCastException is
+ * thrown if it has a different type
+ */
+ public List> getList(int columnIndex) {
+ ListVector vector = (ListVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an int from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present in the Row and a ClassCastException is thrown
+ * if it has a different type
+ */
+ public int getInt(String columnName) {
+ IntVector vector = (IntVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns an int from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present and a ClassCastException is
+ * thrown if it has a different type
+ */
+ public int getInt(int columnIndex) {
+ IntVector vector = (IntVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ */
+ public void getInt(String columnName, NullableIntHolder holder) {
+ IntVector vector = (IntVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present and a ClassCastException is
+ * thrown if it has a different type
+ */
+ public void getInt(int columnIndex, NullableIntHolder holder) {
+ IntVector vector = (IntVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns an int from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present in the Row and a ClassCastException is thrown
+ * if it has a different type
+ */
+ public int getUInt4(String columnName) {
+ UInt4Vector vector = (UInt4Vector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns an int from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present and a ClassCastException is
+ * thrown if it has a different type
+ */
+ public int getUInt4(int columnIndex) {
+ UInt4Vector vector = (UInt4Vector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value at the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ */
+ public void getUInt4(String columnName, NullableUInt4Holder holder) {
+ UInt4Vector vector = (UInt4Vector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value at the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present and a ClassCastException is
+ * thrown if it has a different type
+ */
+ public void getUInt4(int columnIndex, NullableUInt4Holder holder) {
+ UInt4Vector vector = (UInt4Vector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a short from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public short getSmallInt(String columnName) {
+ SmallIntVector vector = (SmallIntVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a short from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public short getSmallInt(int columnIndex) {
+ SmallIntVector vector = (SmallIntVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getSmallInt(String columnName, NullableSmallIntHolder holder) {
+ SmallIntVector vector = (SmallIntVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getSmallInt(int columnIndex, NullableSmallIntHolder holder) {
+ SmallIntVector vector = (SmallIntVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a char from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public char getUInt2(String columnName) {
+ UInt2Vector vector = (UInt2Vector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a char from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public char getUInt2(int columnIndex) {
+ UInt2Vector vector = (UInt2Vector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getUInt2(String columnName, NullableUInt2Holder holder) {
+ UInt2Vector vector = (UInt2Vector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getUInt2(int columnIndex, NullableUInt2Holder holder) {
+ UInt2Vector vector = (UInt2Vector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a byte from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public byte getTinyInt(String columnName) {
+ TinyIntVector vector = (TinyIntVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a byte from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public byte getTinyInt(int columnIndex) {
+ TinyIntVector vector = (TinyIntVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getTinyInt(String columnName, NullableTinyIntHolder holder) {
+ TinyIntVector vector = (TinyIntVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column at the given index and current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getTinyInt(int columnIndex, NullableTinyIntHolder holder) {
+ TinyIntVector vector = (TinyIntVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a byte from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public byte getUInt1(String columnName) {
+ UInt1Vector vector = (UInt1Vector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a byte from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public byte getUInt1(int columnIndex) {
+ UInt1Vector vector = (UInt1Vector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getUInt1(String columnName, NullableUInt1Holder holder) {
+ UInt1Vector vector = (UInt1Vector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getUInt1(int columnIndex, NullableUInt1Holder holder) {
+ UInt1Vector vector = (UInt1Vector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public long getBigInt(String columnName) {
+ BigIntVector vector = (BigIntVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getBigInt(int columnIndex) {
+ BigIntVector vector = (BigIntVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getBigInt(String columnName, NullableBigIntHolder holder) {
+ BigIntVector vector = (BigIntVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getBigInt(int columnIndex, NullableBigIntHolder holder) {
+ BigIntVector vector = (BigIntVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public long getUInt8(String columnName) {
+ UInt8Vector vector = (UInt8Vector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getUInt8(int columnIndex) {
+ UInt8Vector vector = (UInt8Vector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getUInt8(String columnName, NullableUInt8Holder holder) {
+ UInt8Vector vector = (UInt8Vector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getUInt8(int columnIndex, NullableUInt8Holder holder) {
+ UInt8Vector vector = (UInt8Vector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a float from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public float getFloat4(String columnName) {
+ Float4Vector vector = (Float4Vector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a float from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public float getFloat4(int columnIndex) {
+ Float4Vector vector = (Float4Vector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getFloat4(String columnName, NullableFloat4Holder holder) {
+ Float4Vector vector = (Float4Vector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getFloat4(int columnIndex, NullableFloat4Holder holder) {
+ Float4Vector vector = (Float4Vector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a double from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public double getFloat8(String columnName) {
+ Float8Vector vector = (Float8Vector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a double from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public double getFloat8(int columnIndex) {
+ Float8Vector vector = (Float8Vector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row.
+ * An IllegalStateException is thrown if the column is not present, and a ClassCastException is thrown
+ * if it is present but has a different type
+ */
+ public void getFloat8(String columnName, NullableFloat8Holder holder) {
+ Float8Vector vector = (Float8Vector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getFloat8(int columnIndex, NullableFloat8Holder holder) {
+ Float8Vector vector = (Float8Vector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns an int from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public int getBit(String columnName) {
+ BitVector vector = (BitVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns an int from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public int getBit(int columnIndex) {
+ BitVector vector = (BitVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getBit(String columnName, NullableBitHolder holder) {
+ BitVector vector = (BitVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getBit(int columnIndex, NullableBitHolder holder) {
+ BitVector vector = (BitVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public long getTimeNano(String columnName) {
+ TimeNanoVector vector = (TimeNanoVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getTimeNano(int columnIndex) {
+ TimeNanoVector vector = (TimeNanoVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given name at the current row.
+ * An IllegalStateException is thrown if the column is not present, and a ClassCastException is thrown
+ * if it is present but has a different type
+ */
+ public void getTimeNano(String columnName, NullableTimeNanoHolder holder) {
+ TimeNanoVector vector = (TimeNanoVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value in the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type.
+ */
+ public void getTimeNano(int columnIndex, NullableTimeNanoHolder holder) {
+ TimeNanoVector vector = (TimeNanoVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type.
+ */
+ public long getTimeMicro(String columnName) {
+ TimeMicroVector vector = (TimeMicroVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type.
+ */
+ public long getTimeMicro(int columnIndex) {
+ TimeMicroVector vector = (TimeMicroVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row.
+ * An IllegalStateException is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type.
+ */
+ public void getTimeMicro(String columnName, NullableTimeMicroHolder holder) {
+ TimeMicroVector vector = (TimeMicroVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type.
+ */
+ public void getTimeMicro(int columnIndex, NullableTimeMicroHolder holder) {
+ TimeMicroVector vector = (TimeMicroVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns an int from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type.
+ */
+ public int getTimeMilli(String columnName) {
+ TimeMilliVector vector = (TimeMilliVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns an int from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type.
+ */
+ public int getTimeMilli(int columnIndex) {
+ TimeMilliVector vector = (TimeMilliVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row.
+ * An IllegalStateException is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type.
+ */
+ public void getTimeMilli(String columnName, NullableTimeMilliHolder holder) {
+ TimeMilliVector vector = (TimeMilliVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type.
+ */
+ public void getTimeMilli(int columnIndex, NullableTimeMilliHolder holder) {
+ TimeMilliVector vector = (TimeMilliVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a LocalDateTime from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type.
+ */
+ public LocalDateTime getTimeMilliObj(String columnName) {
+ TimeMilliVector vector = (TimeMilliVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a LocalDateTime from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type.
+ */
+ public LocalDateTime getTimeMilliObj(int columnIndex) {
+ TimeMilliVector vector = (TimeMilliVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an int from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type.
+ */
+ public int getTimeSec(String columnName) {
+ TimeSecVector vector = (TimeSecVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns an int from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type.
+ */
+ public int getTimeSec(int columnIndex) {
+ TimeSecVector vector = (TimeSecVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row.
+ * An IllegalStateException is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type.
+ */
+ public void getTimeSec(String columnName, NullableTimeSecHolder holder) {
+ TimeSecVector vector = (TimeSecVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type.
+ */
+ public void getTimeSec(int columnIndex, NullableTimeSecHolder holder) {
+ TimeSecVector vector = (TimeSecVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type.
+ */
+ public long getTimeStampSec(String columnName) {
+ TimeStampSecVector vector = (TimeStampSecVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getTimeStampSec(int columnIndex) {
+ TimeStampSecVector vector = (TimeStampSecVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row.
+ * An IllegalStateException is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public void getTimeStampSec(String columnName, NullableTimeStampSecHolder holder) {
+ TimeStampSecVector vector = (TimeStampSecVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getTimeStampSec(int columnIndex, NullableTimeStampSecHolder holder) {
+ TimeStampSecVector vector = (TimeStampSecVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a LocalDateTime from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public LocalDateTime getTimeStampSecObj(String columnName) {
+ TimeStampSecVector vector = (TimeStampSecVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a LocalDateTime from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public LocalDateTime getTimeStampSecObj(int columnIndex) {
+ TimeStampSecVector vector = (TimeStampSecVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row.
+ * An IllegalStateException is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public long getTimeStampSecTZ(String columnName) {
+ TimeStampSecTZVector vector = (TimeStampSecTZVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getTimeStampSecTZ(int columnIndex) {
+ TimeStampSecTZVector vector = (TimeStampSecTZVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row.
+ * An IllegalStateException is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public void getTimeStampSecTZ(String columnName, NullableTimeStampSecTZHolder holder) {
+ TimeStampSecTZVector vector = (TimeStampSecTZVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row.
+ * An IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getTimeStampSecTZ(int columnIndex, NullableTimeStampSecTZHolder holder) {
+ TimeStampSecTZVector vector = (TimeStampSecTZVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public long getTimeStampNano(String columnName) {
+ TimeStampNanoVector vector = (TimeStampNanoVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getTimeStampNano(int columnIndex) {
+ TimeStampNanoVector vector = (TimeStampNanoVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public void getTimeStampNano(String columnName, NullableTimeStampNanoHolder holder) {
+ TimeStampNanoVector vector = (TimeStampNanoVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getTimeStampNano(int columnIndex, NullableTimeStampNanoHolder holder) {
+ TimeStampNanoVector vector = (TimeStampNanoVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a LocalDateTime from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public LocalDateTime getTimeStampNanoObj(String columnName) {
+ TimeStampNanoVector vector = (TimeStampNanoVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a LocalDateTime from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public LocalDateTime getTimeStampNanoObj(int columnIndex) {
+ TimeStampNanoVector vector = (TimeStampNanoVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public long getTimeStampNanoTZ(String columnName) {
+ TimeStampNanoTZVector vector = (TimeStampNanoTZVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getTimeStampNanoTZ(int columnIndex) {
+ TimeStampNanoTZVector vector = (TimeStampNanoTZVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public void getTimeStampNanoTZ(String columnName, NullableTimeStampNanoTZHolder holder) {
+ TimeStampNanoTZVector vector = (TimeStampNanoTZVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getTimeStampNanoTZ(int columnIndex, NullableTimeStampNanoTZHolder holder) {
+ TimeStampNanoTZVector vector = (TimeStampNanoTZVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public long getTimeStampMilli(String columnName) {
+ TimeStampMilliVector vector = (TimeStampMilliVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getTimeStampMilli(int columnIndex) {
+ TimeStampMilliVector vector = (TimeStampMilliVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public void getTimeStampMilli(String columnName, NullableTimeStampMilliHolder holder) {
+ TimeStampMilliVector vector = (TimeStampMilliVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getTimeStampMilli(int columnIndex, NullableTimeStampMilliHolder holder) {
+ TimeStampMilliVector vector = (TimeStampMilliVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a LocalDateTime from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public LocalDateTime getTimeStampMilliObj(String columnName) {
+ TimeStampMilliVector vector = (TimeStampMilliVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a LocalDateTime from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public LocalDateTime getTimeStampMilliObj(int columnIndex) {
+ TimeStampMilliVector vector = (TimeStampMilliVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public long getTimeStampMilliTZ(String columnName) {
+ TimeStampMilliTZVector vector = (TimeStampMilliTZVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getTimeStampMilliTZ(int columnIndex) {
+ TimeStampMilliTZVector vector = (TimeStampMilliTZVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different types
+ */
+ public void getTimeStampMilliTZ(String columnName, NullableTimeStampMilliTZHolder holder) {
+ TimeStampMilliTZVector vector = (TimeStampMilliTZVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getTimeStampMilliTZ(int columnIndex, NullableTimeStampMilliTZHolder holder) {
+ TimeStampMilliTZVector vector = (TimeStampMilliTZVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public long getTimeStampMicro(String columnName) {
+ TimeStampMicroVector vector = (TimeStampMicroVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getTimeStampMicro(int columnIndex) {
+ TimeStampMicroVector vector = (TimeStampMicroVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public void getTimeStampMicro(String columnName, NullableTimeStampMicroHolder holder) {
+ TimeStampMicroVector vector = (TimeStampMicroVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getTimeStampMicro(int columnIndex, NullableTimeStampMicroHolder holder) {
+ TimeStampMicroVector vector = (TimeStampMicroVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a LocalDateTime from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public LocalDateTime getTimeStampMicroObj(String columnName) {
+ TimeStampMicroVector vector = (TimeStampMicroVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a LocalDateTime from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public LocalDateTime getTimeStampMicroObj(int columnIndex) {
+ TimeStampMicroVector vector = (TimeStampMicroVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public long getTimeStampMicroTZ(String columnName) {
+ TimeStampMicroTZVector vector = (TimeStampMicroTZVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a long from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public long getTimeStampMicroTZ(int columnIndex) {
+ TimeStampMicroTZVector vector = (TimeStampMicroTZVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public void getTimeStampMicroTZ(String columnName, NullableTimeStampMicroTZHolder holder) {
+ TimeStampMicroTZVector vector = (TimeStampMicroTZVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getTimeStampMicroTZ(int columnIndex, NullableTimeStampMicroTZHolder holder) {
+ TimeStampMicroTZVector vector = (TimeStampMicroTZVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a Duration from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public Duration getDurationObj(String columnName) {
+ DurationVector vector = (DurationVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a Duration from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public Duration getDurationObj(int columnIndex) {
+ DurationVector vector = (DurationVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an ArrowBuf from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public ArrowBuf getDuration(String columnName) {
+ DurationVector vector = (DurationVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns an ArrowBuf from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public ArrowBuf getDuration(int columnIndex) {
+ DurationVector vector = (DurationVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getDuration(String columnName, NullableDurationHolder holder) {
+ DurationVector vector = (DurationVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getDuration(int columnIndex, NullableDurationHolder holder) {
+ DurationVector vector = (DurationVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a PeriodDuration from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public PeriodDuration getIntervalMonthDayNanoObj(String columnName) {
+ IntervalMonthDayNanoVector vector = (IntervalMonthDayNanoVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a PeriodDuration from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public PeriodDuration getIntervalMonthDayNanoObj(int columnIndex) {
+ IntervalMonthDayNanoVector vector = (IntervalMonthDayNanoVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an ArrowBuf from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public ArrowBuf getIntervalMonthDayNano(String columnName) {
+ IntervalMonthDayNanoVector vector = (IntervalMonthDayNanoVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns an ArrowBuf from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public ArrowBuf getIntervalMonthDayNano(int columnIndex) {
+ IntervalMonthDayNanoVector vector = (IntervalMonthDayNanoVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getIntervalMonthDayNano(
+ String columnName, NullableIntervalMonthDayNanoHolder holder) {
+ IntervalMonthDayNanoVector vector = (IntervalMonthDayNanoVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getIntervalMonthDayNano(int columnIndex, NullableIntervalMonthDayNanoHolder holder) {
+ IntervalMonthDayNanoVector vector = (IntervalMonthDayNanoVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns an ArrowBuf from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public ArrowBuf getIntervalDay(String columnName) {
+ IntervalDayVector vector = (IntervalDayVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns an ArrowBuf from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public ArrowBuf getIntervalDay(int columnIndex) {
+ IntervalDayVector vector = (IntervalDayVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getIntervalDay(String columnName, NullableIntervalDayHolder holder) {
+ IntervalDayVector vector = (IntervalDayVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getIntervalDay(int columnIndex, NullableIntervalDayHolder holder) {
+ IntervalDayVector vector = (IntervalDayVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a Duration from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public Duration getIntervalDayObj(int columnIndex) {
+ IntervalDayVector vector = (IntervalDayVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a Duration from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public Duration getIntervalDayObj(String columnName) {
+ IntervalDayVector vector = (IntervalDayVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a Period from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public Period getIntervalYearObj(String columnName) {
+ IntervalYearVector vector = (IntervalYearVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a Period from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public Period getIntervalYearObj(int columnIndex) {
+ IntervalYearVector vector = (IntervalYearVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an int from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public int getIntervalYear(String columnName) {
+ IntervalYearVector vector = (IntervalYearVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns an int from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public int getIntervalYear(int columnIndex) {
+ IntervalYearVector vector = (IntervalYearVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Updates the holder with the value from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getIntervalYear(String columnName, NullableIntervalYearHolder holder) {
+ IntervalYearVector vector = (IntervalYearVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the holder with the value from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getIntervalYear(int columnIndex, NullableIntervalYearHolder holder) {
+ IntervalYearVector vector = (IntervalYearVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the value of the holder with data from vector at the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getDecimal(int columnIndex, NullableDecimalHolder holder) {
+ DecimalVector vector = (DecimalVector) table.getVector(columnIndex);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Updates the value of the holder with data from the vector with given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public void getDecimal(String columnName, NullableDecimalHolder holder) {
+ DecimalVector vector = (DecimalVector) table.getVector(columnName);
+ vector.get(rowNumber, holder);
+ }
+
+ /**
+ * Returns a BigDecimal from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public BigDecimal getDecimalObj(String columnName) {
+ DecimalVector vector = (DecimalVector) table.getVector(columnName);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns a BigDecimal from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public BigDecimal getDecimalObj(int columnIndex) {
+ DecimalVector vector = (DecimalVector) table.getVector(columnIndex);
+ return vector.getObject(rowNumber);
+ }
+
+ /**
+ * Returns an ArrowBuf from the column of the given name at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public ArrowBuf getDecimal(String columnName) {
+ DecimalVector vector = (DecimalVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns an ArrowBuf from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public ArrowBuf getDecimal(int columnIndex) {
+ DecimalVector vector = (DecimalVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a byte[] from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public byte[] getVarBinary(String columnName) {
+ VarBinaryVector vector = (VarBinaryVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a byte[] from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public byte[] getVarBinary(int columnIndex) {
+ VarBinaryVector vector = (VarBinaryVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a byte[] from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public byte[] getFixedSizeBinary(String columnName) {
+ FixedSizeBinaryVector vector = (FixedSizeBinaryVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a byte[] from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public byte[] getFixedSizeBinary(int columnIndex) {
+ FixedSizeBinaryVector vector = (FixedSizeBinaryVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a byte[] from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present, and a ClassCastException is thrown if it is
+ * present but has a different type
+ */
+ public byte[] getLargeVarBinary(String columnName) {
+ LargeVarBinaryVector vector = (LargeVarBinaryVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a byte[] from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present, and a ClassCastException
+ * is thrown if it is present but has a different type
+ */
+ public byte[] getLargeVarBinary(int columnIndex) {
+ LargeVarBinaryVector vector = (LargeVarBinaryVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a String from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present in the Row and a ClassCastException is thrown
+ * if it has a different type
+ *
+ *
StandardCharsets.UTF_8 is used as the charset
+ */
+ public String getVarCharObj(String columnName) {
+ VarCharVector vector = (VarCharVector) table.getVector(columnName);
+ return new String(vector.get(rowNumber), getDefaultCharacterSet());
+ }
+
+ /**
+ * Returns a String from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ *
+ * @param columnIndex the index of the FieldVector holding the value
+ */
+ public String getVarCharObj(int columnIndex) {
+ VarCharVector vector = (VarCharVector) table.getVector(columnIndex);
+ return new String(vector.get(rowNumber), getDefaultCharacterSet());
+ }
+
+ /**
+ * Returns a byte[] from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present in the Row and a ClassCastException is thrown
+ * if it has a different type
+ *
+ *
StandardCharsets.UTF_8 is used as the charset
+ */
+ public byte[] getVarChar(String columnName) {
+ VarCharVector vector = (VarCharVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a byte[] from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ *
+ * @param columnIndex the index of the FieldVector holding the value
+ */
+ public byte[] getVarChar(int columnIndex) {
+ VarCharVector vector = (VarCharVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a String from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present in the Row and a ClassCastException is thrown
+ * if it has a different type
+ *
+ *
StandardCharsets.UTF_8 is used as the charset, unless this cursor was created with a default
+ * Charset
+ */
+ public String getLargeVarCharObj(String columnName) {
+ LargeVarCharVector vector = (LargeVarCharVector) table.getVector(columnName);
+ return new String(vector.get(rowNumber), getDefaultCharacterSet());
+ }
+
+ /**
+ * Returns a String from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ */
+ public String getLargeVarCharObj(int columnIndex) {
+ LargeVarCharVector vector = (LargeVarCharVector) table.getVector(columnIndex);
+ return new String(vector.get(rowNumber), getDefaultCharacterSet());
+ }
+
+ /**
+ * Returns a byte[] from the column of the given name at the current row. An IllegalStateException
+ * is thrown if the column is not present in the Row and a ClassCastException is thrown
+ * if it has a different type
+ *
+ *
StandardCharsets.UTF_8 is used as the charset, unless this cursor was created with a default
+ * Charset
+ */
+ public byte[] getLargeVarChar(String columnName) {
+ LargeVarCharVector vector = (LargeVarCharVector) table.getVector(columnName);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns a byte[] from the column with the given index at the current row. An
+ * IllegalStateException is thrown if the column is not present in the Row and an
+ * ClassCastException is thrown if it has a different type
+ */
+ public byte[] getLargeVarChar(int columnIndex) {
+ LargeVarCharVector vector = (LargeVarCharVector) table.getVector(columnIndex);
+ return vector.get(rowNumber);
+ }
+
+ /**
+ * Returns true if there is at least one more non-deleted row in the table that has yet to be
+ * processed.
+ */
+ @Override
+ public boolean hasNext() {
+ return nextRowSet || setNextObject();
+ }
+
+ /**
+ * Returns the next non-deleted row in the table.
+ *
+ * @throws NoSuchElementException if there are no more rows
+ */
+ @Override
+ public Row next() {
+ if (!nextRowSet && !setNextObject()) {
+ throw new NoSuchElementException();
+ }
+ nextRowSet = false;
+ return this;
+ }
+
+ /**
+ * Set rowNumber to the next non-deleted row. If there are no more rows return false. Otherwise,
+ * return true.
+ */
+ private boolean setNextObject() {
+ while (iterator.hasNext()) {
+ final int row = iterator.next();
+ if (!rowIsDeleted(row)) {
+ rowNumber = row;
+ nextRowSet = true;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns new internal iterator that processes every row, deleted or not. Use the
+ * wrapping next() and hasNext() methods rather than using this iterator directly, unless you want
+ * to see any deleted rows.
+ */
+ private Iterator intIterator() {
+ return new Iterator() {
+
+ @Override
+ public boolean hasNext() {
+ return rowNumber < table.getRowCount() - 1;
+ }
+
+ @Override
+ public Integer next() {
+ rowNumber++;
+ return rowNumber;
+ }
+ };
+ }
+
+ public int getRowNumber() {
+ return rowNumber;
+ }
+
+ private boolean rowIsDeleted(int rowNumber) {
+ return table.isRowDeleted(rowNumber);
+ }
+
+ /**
+ * Returns the default character set for use with character vectors.
+ */
+ public Charset getDefaultCharacterSet() {
+ return DEFAULT_CHARACTER_SET;
+ }
+}
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/table/Table.java b/java/vector/src/main/java/org/apache/arrow/vector/table/Table.java
new file mode 100644
index 00000000000..37cdf9eb1e2
--- /dev/null
+++ b/java/vector/src/main/java/org/apache/arrow/vector/table/Table.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.arrow.vector.table;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import org.apache.arrow.util.Preconditions;
+import org.apache.arrow.vector.FieldVector;
+import org.apache.arrow.vector.VectorSchemaRoot;
+import org.apache.arrow.vector.dictionary.DictionaryProvider;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * Table is an immutable tabular data structure.
+ *
+ * See {@link VectorSchemaRoot} for batch processing use cases
+ *
+ *
+ * This API is EXPERIMENTAL.
+ */
+public class Table extends BaseTable implements Iterable {
+
+ /** Constructs new instance containing each of the given vectors. */
+ public Table(Iterable vectors) {
+ this(StreamSupport.stream(vectors.spliterator(), false).collect(Collectors.toList()));
+ }
+
+ /** Constructs a new instance from vectors. */
+ public static Table of(FieldVector... vectors) {
+ return new Table(Arrays.stream(vectors).collect(Collectors.toList()));
+ }
+
+ /**
+ * Constructs a new instance with the number of rows set to the value count of the first
+ * FieldVector.
+ *
+ * All vectors must have the same value count. Although this is not checked, inconsistent
+ * counts may lead to exceptions or other undefined behavior later.
+ *
+ * @param fieldVectors The data vectors (must be equal in size to fields.
+ */
+ public Table(List fieldVectors) {
+ this(fieldVectors, fieldVectors.size() == 0 ? 0 : fieldVectors.get(0).getValueCount());
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param fieldVectors The data vectors.
+ * @param rowCount The number of rows
+ */
+ public Table(List fieldVectors, int rowCount) {
+ super(fieldVectors, rowCount, null);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param fieldVectors The data vectors.
+ * @param rowCount The number of rows
+ * @param provider A dictionary provider. May be null if none of the vectors is dictionary encoded
+ */
+ public Table(List fieldVectors, int rowCount, DictionaryProvider provider) {
+ super(fieldVectors, rowCount, provider);
+ }
+
+ /**
+ * Constructs a new instance containing the data from the argument. Vectors are shared between the
+ * Table and VectorSchemaRoot. Direct modification of those vectors is unsafe and should be
+ * avoided.
+ *
+ * @param vsr The VectorSchemaRoot providing data for this Table
+ */
+ public Table(VectorSchemaRoot vsr) {
+ this(vsr.getFieldVectors(), vsr.getRowCount());
+ vsr.clear();
+ }
+
+ /**
+ * Returns a new Table created by adding the given vector to the vectors in this Table.
+ *
+ * @param index field index
+ * @param vector vector to be added.
+ * @return out a new Table with vector added
+ */
+ public Table addVector(int index, FieldVector vector) {
+ return new Table(insertVector(index, vector));
+ }
+
+ /**
+ * Returns a new Table created by removing the selected Vector from this Table.
+ *
+ * @param index field index
+ * @return out a new Table with vector removed
+ */
+ public Table removeVector(int index) {
+ return new Table(extractVector(index));
+ }
+
+ /**
+ * Slice this table from desired index. Memory is NOT transferred from the vectors in this table
+ * to new vectors in the target table. This table is unchanged.
+ *
+ * @param index start position of the slice
+ * @return the sliced table
+ */
+ public Table slice(int index) {
+ return slice(index, this.rowCount - index);
+ }
+
+ /**
+ * Slice this table at desired index and length. Memory is NOT transferred from the vectors in
+ * this table to new vectors in the target table. This table is unchanged.
+ *
+ * @param index start position of the slice
+ * @param length length of the slice
+ * @return the sliced table
+ */
+ public Table slice(int index, int length) {
+ Preconditions.checkArgument(index >= 0, "expecting non-negative index");
+ Preconditions.checkArgument(length >= 0, "expecting non-negative length");
+ Preconditions.checkArgument(index + length <= rowCount, "index + length should <= rowCount");
+
+ if (index == 0 && length == rowCount) {
+ return this;
+ }
+
+ List sliceVectors =
+ fieldVectors.stream()
+ .map(
+ v -> {
+ TransferPair transferPair = v.getTransferPair(v.getAllocator());
+ transferPair.splitAndTransfer(index, length);
+ return (FieldVector) transferPair.getTo();
+ })
+ .collect(Collectors.toList());
+
+ return new Table(sliceVectors);
+ }
+
+ /** Returns a Row iterator for this Table. */
+ @Override
+ public Iterator iterator() {
+
+ return new Iterator() {
+
+ private final Row row = new Row(Table.this);
+
+ @Override
+ public Row next() {
+ row.next();
+ return row;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return row.hasNext();
+ }
+ };
+ }
+}
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/table/package-info.java b/java/vector/src/main/java/org/apache/arrow/vector/table/package-info.java
new file mode 100644
index 00000000000..7133183a28a
--- /dev/null
+++ b/java/vector/src/main/java/org/apache/arrow/vector/table/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.arrow.vector.table;
+
+/**
+ * Support for Table, an immutable, columnar, tabular data structure based on FieldVectors.
+ *
+ * See the README.md file in this directory for detailed information about Table class and supporting classes.
+ *
+ */
diff --git a/java/vector/src/test/java/org/apache/arrow/vector/table/BaseTableTest.java b/java/vector/src/test/java/org/apache/arrow/vector/table/BaseTableTest.java
new file mode 100644
index 00000000000..6812785e72b
--- /dev/null
+++ b/java/vector/src/test/java/org/apache/arrow/vector/table/BaseTableTest.java
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.arrow.vector.table;
+
+import static org.apache.arrow.vector.table.TestUtils.INT_VECTOR_NAME;
+import static org.apache.arrow.vector.table.TestUtils.INT_VECTOR_NAME_1;
+import static org.apache.arrow.vector.table.TestUtils.INT_VECTOR_NAME_2;
+import static org.apache.arrow.vector.table.TestUtils.intPlusVarcharColumns;
+import static org.apache.arrow.vector.table.TestUtils.twoIntColumns;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.memory.RootAllocator;
+import org.apache.arrow.vector.FieldVector;
+import org.apache.arrow.vector.IntVector;
+import org.apache.arrow.vector.VarCharVector;
+import org.apache.arrow.vector.VectorSchemaRoot;
+import org.apache.arrow.vector.dictionary.Dictionary;
+import org.apache.arrow.vector.dictionary.DictionaryEncoder;
+import org.apache.arrow.vector.dictionary.DictionaryProvider;
+import org.apache.arrow.vector.types.pojo.ArrowType;
+import org.apache.arrow.vector.types.pojo.DictionaryEncoding;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class BaseTableTest {
+
+ private BufferAllocator allocator;
+
+ @BeforeEach
+ public void init() {
+ allocator = new RootAllocator(Long.MAX_VALUE);
+ }
+
+ @Test
+ void getReaderByName() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ assertNotNull(t.getReader(INT_VECTOR_NAME_1));
+ }
+ }
+
+ @Test
+ void getReaderByIndex() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ assertNotNull(t.getReader(0));
+ }
+ }
+
+ @Test
+ void getReaderByField() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ assertNotNull(t.getReader(t.getField(INT_VECTOR_NAME_1)));
+ }
+ }
+
+ @Test
+ void getSchema() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ assertNotNull(t.getSchema());
+ assertEquals(2, t.getSchema().getFields().size());
+ }
+ }
+
+ @Test
+ void insertVector() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ ArrowType intArrowType = new ArrowType.Int(32, true);
+ FieldType intFieldType = new FieldType(true, intArrowType, null);
+ IntVector v3 = new IntVector("3", intFieldType, allocator);
+ List revisedVectors = t.insertVector(2, v3);
+ assertEquals(3, revisedVectors.size());
+ assertEquals(v3, revisedVectors.get(2));
+ }
+ }
+
+ @Test
+ void insertVectorFirstPosition() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ ArrowType intArrowType = new ArrowType.Int(32, true);
+ FieldType intFieldType = new FieldType(true, intArrowType, null);
+ IntVector v3 = new IntVector("3", intFieldType, allocator);
+ List revisedVectors = t.insertVector(0, v3);
+ assertEquals(3, revisedVectors.size());
+ assertEquals(v3, revisedVectors.get(0));
+ }
+ }
+
+ @Test
+ void extractVector() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ List revisedVectors = t.extractVector(0);
+ assertEquals(2, t.getVectorCount()); // vector not removed from table yet
+ assertEquals(1, revisedVectors.size());
+ }
+ }
+
+ @Test
+ void close() {
+ IntVector v = new IntVector(INT_VECTOR_NAME, allocator);
+ v.setSafe(0, 132);
+ List vectors = new ArrayList<>();
+ vectors.add(v);
+ v.setValueCount(1);
+ try (Table t = new Table(vectors)) {
+ t.close();
+ for (FieldVector fieldVector : t.fieldVectors) {
+ assertEquals(0, fieldVector.getValueCount());
+ }
+ }
+ }
+
+ @Test
+ void getRowCount() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ // TODO: handle setting rowcount on Table construction
+ assertEquals(2, t.getRowCount());
+ }
+ }
+
+ @Test
+ void toVectorSchemaRoot() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ assertNotNull(t.getVector(INT_VECTOR_NAME_1));
+ assertNotNull(t.getVector(INT_VECTOR_NAME_2));
+ VectorSchemaRoot vsr = t.toVectorSchemaRoot();
+ assertNotNull(vsr.getVector(INT_VECTOR_NAME_1));
+ assertNotNull(vsr.getVector(INT_VECTOR_NAME_2));
+ assertEquals(
+ t.getSchema().findField(INT_VECTOR_NAME_1), vsr.getSchema().findField(INT_VECTOR_NAME_1));
+ }
+ }
+
+ @Test
+ void getVector() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ assertNotNull(t.getVector(0));
+ }
+ }
+
+ @Test
+ void testGetVector() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ assertNotNull(t.getVector(INT_VECTOR_NAME_1));
+ assertThrows(IllegalStateException.class,
+ () -> t.getVector("wrong name"));
+ }
+ }
+
+ @Test
+ void immutableCursor() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ assertNotNull(t.immutableRow());
+ }
+ }
+
+ @Test
+ void contentToTsvString() {
+ IntVector v = new IntVector(INT_VECTOR_NAME, allocator);
+ v.setSafe(0, 1);
+ v.setSafe(1, 2);
+ v.setSafe(2, 3);
+ v.setValueCount(3);
+
+ try (Table t = Table.of(v)) {
+ assertEquals(3, t.rowCount);
+ List values = new ArrayList<>();
+ for (Row r : t) {
+ values.add(r.getInt(INT_VECTOR_NAME));
+ }
+ assertEquals(3, values.size());
+ List intList = new ArrayList<>();
+ intList.add(1);
+ intList.add(2);
+ intList.add(3);
+ assertTrue(values.containsAll(intList));
+ String printed = "intCol\n" + "1\n" + "2\n" + "3\n";
+ assertEquals(printed, t.contentToTSVString());
+ }
+ }
+
+ @Test
+ void isDeletedRow() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ assertFalse(t.isRowDeleted(0));
+ assertFalse(t.isRowDeleted(1));
+ }
+ }
+
+ @Test
+ void testEncode() {
+ List vectorList = intPlusVarcharColumns(allocator);
+ VarCharVector original = (VarCharVector) vectorList.get(1);
+ DictionaryProvider provider = getDictionary();
+ try (Table t = new Table(vectorList, vectorList.get(0).getValueCount(), provider)) {
+ IntVector v = (IntVector) t.encode(original.getName(), 1L);
+ assertNotNull(v);
+ assertEquals(0, v.get(0));
+ assertEquals(1, v.get(1));
+ }
+ }
+
+ @Test
+ void testDecode() {
+ List vectorList = intPlusVarcharColumns(allocator);
+ VarCharVector original = (VarCharVector) vectorList.get(1);
+
+ VarCharVector dictionaryVector = new VarCharVector("dictionary", allocator);
+ dictionaryVector.allocateNew(2);
+ dictionaryVector.set(0, "one".getBytes());
+ dictionaryVector.set(1, "two".getBytes());
+ dictionaryVector.setValueCount(2);
+ Dictionary dictionary =
+ new Dictionary(dictionaryVector, new DictionaryEncoding(1L, false, null));
+
+ DictionaryEncoder encoder = new DictionaryEncoder(dictionary, allocator);
+ IntVector encoded = (IntVector) encoder.encode(original);
+ vectorList.remove(original);
+ vectorList.add(encoded);
+ DictionaryProvider provider = getDictionary();
+
+ try (Table t = new Table(vectorList, vectorList.get(0).getValueCount(), provider)) {
+ VarCharVector v = (VarCharVector) t.decode(encoded.getName(), 1L);
+ assertNotNull(v);
+ assertEquals("one", new String(v.get(0)));
+ assertEquals("two", new String(v.get(1)));
+ }
+ }
+
+ @Test
+ void getProvider() {
+ List vectorList = intPlusVarcharColumns(allocator);
+ DictionaryProvider provider = getDictionary();
+ try (Table t = new Table(vectorList, vectorList.get(0).getValueCount(), provider)) {
+ assertEquals(provider, t.getDictionaryProvider());
+ }
+ }
+
+ private DictionaryProvider getDictionary() {
+
+ DictionaryProvider.MapDictionaryProvider provider =
+ new DictionaryProvider.MapDictionaryProvider();
+ DictionaryEncoding encoding = new DictionaryEncoding(1L, false, null);
+
+ VarCharVector dictionaryVector = new VarCharVector("dictionary", allocator);
+ dictionaryVector.allocateNew(2);
+ dictionaryVector.set(0, "one".getBytes());
+ dictionaryVector.set(1, "two".getBytes());
+ dictionaryVector.setValueCount(2);
+
+ Dictionary dictionary = new Dictionary(dictionaryVector, encoding);
+ provider.put(dictionary);
+ return provider;
+ }
+}
diff --git a/java/vector/src/test/java/org/apache/arrow/vector/table/RowTest.java b/java/vector/src/test/java/org/apache/arrow/vector/table/RowTest.java
new file mode 100644
index 00000000000..8feaddbeb35
--- /dev/null
+++ b/java/vector/src/test/java/org/apache/arrow/vector/table/RowTest.java
@@ -0,0 +1,856 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.arrow.vector.table;
+
+import static org.apache.arrow.vector.table.TestUtils.BIGINT_INT_MAP_VECTOR_NAME;
+import static org.apache.arrow.vector.table.TestUtils.FIXEDBINARY_VECTOR_NAME_1;
+import static org.apache.arrow.vector.table.TestUtils.INT_LIST_VECTOR_NAME;
+import static org.apache.arrow.vector.table.TestUtils.INT_VECTOR_NAME_1;
+import static org.apache.arrow.vector.table.TestUtils.STRUCT_VECTOR_NAME;
+import static org.apache.arrow.vector.table.TestUtils.UNION_VECTOR_NAME;
+import static org.apache.arrow.vector.table.TestUtils.VARBINARY_VECTOR_NAME_1;
+import static org.apache.arrow.vector.table.TestUtils.VARCHAR_VECTOR_NAME_1;
+import static org.apache.arrow.vector.table.TestUtils.fixedWidthVectors;
+import static org.apache.arrow.vector.table.TestUtils.intPlusFixedBinaryColumns;
+import static org.apache.arrow.vector.table.TestUtils.intPlusLargeVarBinaryColumns;
+import static org.apache.arrow.vector.table.TestUtils.intPlusLargeVarcharColumns;
+import static org.apache.arrow.vector.table.TestUtils.intPlusVarBinaryColumns;
+import static org.apache.arrow.vector.table.TestUtils.intPlusVarcharColumns;
+import static org.apache.arrow.vector.table.TestUtils.simpleDenseUnionVector;
+import static org.apache.arrow.vector.table.TestUtils.simpleListVector;
+import static org.apache.arrow.vector.table.TestUtils.simpleMapVector;
+import static org.apache.arrow.vector.table.TestUtils.simpleStructVector;
+import static org.apache.arrow.vector.table.TestUtils.simpleUnionVector;
+import static org.apache.arrow.vector.table.TestUtils.timezoneTemporalVectors;
+import static org.apache.arrow.vector.table.TestUtils.twoIntColumns;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.time.Period;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.memory.RootAllocator;
+import org.apache.arrow.vector.BitVector;
+import org.apache.arrow.vector.DecimalVector;
+import org.apache.arrow.vector.DurationVector;
+import org.apache.arrow.vector.FieldVector;
+import org.apache.arrow.vector.IntervalDayVector;
+import org.apache.arrow.vector.IntervalMonthDayNanoVector;
+import org.apache.arrow.vector.IntervalYearVector;
+import org.apache.arrow.vector.PeriodDuration;
+import org.apache.arrow.vector.VectorSchemaRoot;
+import org.apache.arrow.vector.complex.DenseUnionVector;
+import org.apache.arrow.vector.complex.ListVector;
+import org.apache.arrow.vector.complex.MapVector;
+import org.apache.arrow.vector.complex.StructVector;
+import org.apache.arrow.vector.complex.UnionVector;
+import org.apache.arrow.vector.holders.NullableBigIntHolder;
+import org.apache.arrow.vector.holders.NullableBitHolder;
+import org.apache.arrow.vector.holders.NullableDecimalHolder;
+import org.apache.arrow.vector.holders.NullableDurationHolder;
+import org.apache.arrow.vector.holders.NullableFloat4Holder;
+import org.apache.arrow.vector.holders.NullableFloat8Holder;
+import org.apache.arrow.vector.holders.NullableIntHolder;
+import org.apache.arrow.vector.holders.NullableIntervalDayHolder;
+import org.apache.arrow.vector.holders.NullableIntervalMonthDayNanoHolder;
+import org.apache.arrow.vector.holders.NullableIntervalYearHolder;
+import org.apache.arrow.vector.holders.NullableSmallIntHolder;
+import org.apache.arrow.vector.holders.NullableTimeMicroHolder;
+import org.apache.arrow.vector.holders.NullableTimeMilliHolder;
+import org.apache.arrow.vector.holders.NullableTimeNanoHolder;
+import org.apache.arrow.vector.holders.NullableTimeSecHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampMicroHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampMicroTZHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampMilliHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampMilliTZHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampNanoHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampNanoTZHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampSecHolder;
+import org.apache.arrow.vector.holders.NullableTimeStampSecTZHolder;
+import org.apache.arrow.vector.holders.NullableTinyIntHolder;
+import org.apache.arrow.vector.holders.NullableUInt1Holder;
+import org.apache.arrow.vector.holders.NullableUInt2Holder;
+import org.apache.arrow.vector.holders.NullableUInt4Holder;
+import org.apache.arrow.vector.holders.NullableUInt8Holder;
+import org.apache.arrow.vector.types.IntervalUnit;
+import org.apache.arrow.vector.types.TimeUnit;
+import org.apache.arrow.vector.types.pojo.ArrowType;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.types.pojo.TestExtensionType;
+import org.apache.arrow.vector.util.JsonStringHashMap;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class RowTest {
+
+ private BufferAllocator allocator;
+
+ @BeforeEach
+ public void init() {
+ allocator = new RootAllocator(Long.MAX_VALUE);
+ }
+
+ @AfterEach
+ public void terminate() {
+ allocator.close();
+ }
+
+ @Test
+ void constructor() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ assertEquals(StandardCharsets.UTF_8, c.getDefaultCharacterSet());
+ }
+ }
+
+ @Test
+ void at() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ assertEquals(c.getRowNumber(), -1);
+ c.setPosition(1);
+ assertEquals(c.getRowNumber(), 1);
+ }
+ }
+
+ @Test
+ void getIntByVectorIndex() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertEquals(2, c.getInt(0));
+ }
+ }
+
+ @Test
+ void getIntByVectorName() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertEquals(2, c.getInt(INT_VECTOR_NAME_1));
+ }
+ }
+
+ @Test
+ void testNameNotFound() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertThrows(IllegalStateException.class,
+ () -> c.getVarCharObj("wrong name"));
+ }
+ }
+
+ @Test
+ void testWrongType() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertThrows(ClassCastException.class,
+ () -> c.getVarCharObj(INT_VECTOR_NAME_1));
+ }
+ }
+
+ @Test
+ void getDecimal() {
+ List vectors = new ArrayList<>();
+ DecimalVector decimalVector = new DecimalVector("decimal_vector", allocator, 55, 10);
+ vectors.add(decimalVector);
+ decimalVector.setSafe(0, new BigDecimal("0.0543278923"));
+ decimalVector.setSafe(1, new BigDecimal("2.0543278923"));
+ decimalVector.setValueCount(2);
+ BigDecimal one = decimalVector.getObject(1);
+
+ NullableDecimalHolder holder1 = new NullableDecimalHolder();
+ NullableDecimalHolder holder2 = new NullableDecimalHolder();
+ try (Table t = new Table(vectors)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertEquals(one, c.getDecimalObj("decimal_vector"));
+ assertEquals(one, c.getDecimalObj(0));
+ c.getDecimal(0, holder1);
+ c.getDecimal("decimal_vector", holder2);
+ assertEquals(holder1.buffer, holder2.buffer);
+ assertEquals(c.getDecimal(0).memoryAddress(), c.getDecimal("decimal_vector").memoryAddress());
+ }
+ }
+
+ @Test
+ void getDuration() {
+ List vectors = new ArrayList<>();
+ TimeUnit unit = TimeUnit.SECOND;
+ final FieldType fieldType = FieldType.nullable(new ArrowType.Duration(unit));
+
+ DurationVector durationVector = new DurationVector("duration_vector", fieldType, allocator);
+ NullableDurationHolder holder1 = new NullableDurationHolder();
+ NullableDurationHolder holder2 = new NullableDurationHolder();
+
+ holder1.value = 100;
+ holder1.unit = TimeUnit.SECOND;
+ holder1.isSet = 1;
+ holder2.value = 200;
+ holder2.unit = TimeUnit.SECOND;
+ holder2.isSet = 1;
+
+ vectors.add(durationVector);
+ durationVector.setSafe(0, holder1);
+ durationVector.setSafe(1, holder2);
+ durationVector.setValueCount(2);
+
+ Duration one = durationVector.getObject(1);
+ try (Table t = new Table(vectors)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertEquals(one, c.getDurationObj("duration_vector"));
+ assertEquals(one, c.getDurationObj(0));
+ c.getDuration(0, holder1);
+ c.getDuration("duration_vector", holder2);
+ assertEquals(holder1.value, holder2.value);
+ ArrowBuf durationBuf1 = c.getDuration(0);
+ ArrowBuf durationBuf2 = c.getDuration("duration_vector");
+ assertEquals(durationBuf1.memoryAddress(), durationBuf2.memoryAddress());
+ }
+ }
+
+ @Test
+ void getIntervalDay() {
+ List vectors = new ArrayList<>();
+ IntervalUnit unit = IntervalUnit.DAY_TIME;
+ final FieldType fieldType = FieldType.nullable(new ArrowType.Interval(unit));
+
+ IntervalDayVector intervalDayVector = new IntervalDayVector("intervalDay_vector", fieldType, allocator);
+ NullableIntervalDayHolder holder1 = new NullableIntervalDayHolder();
+ NullableIntervalDayHolder holder2 = new NullableIntervalDayHolder();
+
+ holder1.days = 100;
+ holder1.milliseconds = 1000;
+ holder1.isSet = 1;
+ holder2.days = 200;
+ holder2.milliseconds = 2000;
+ holder2.isSet = 1;
+
+ vectors.add(intervalDayVector);
+ intervalDayVector.setSafe(0, holder1);
+ intervalDayVector.setSafe(1, holder2);
+ intervalDayVector.setValueCount(2);
+
+ Duration one = intervalDayVector.getObject(1);
+ try (Table t = new Table(vectors)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertEquals(one, c.getIntervalDayObj("intervalDay_vector"));
+ assertEquals(one, c.getIntervalDayObj(0));
+ c.getIntervalDay(0, holder1);
+ c.getIntervalDay("intervalDay_vector", holder2);
+ assertEquals(holder1.days, holder2.days);
+ assertEquals(holder1.milliseconds, holder2.milliseconds);
+ ArrowBuf intDayBuf1 = c.getIntervalDay(0);
+ ArrowBuf intDayBuf2 = c.getIntervalDay("intervalDay_vector");
+ assertEquals(intDayBuf1.memoryAddress(), intDayBuf2.memoryAddress());
+ }
+ }
+
+ @Test
+ void getIntervalMonth() {
+ List vectors = new ArrayList<>();
+ IntervalUnit unit = IntervalUnit.MONTH_DAY_NANO;
+ final FieldType fieldType = FieldType.nullable(new ArrowType.Interval(unit));
+
+ IntervalMonthDayNanoVector intervalMonthVector =
+ new IntervalMonthDayNanoVector("intervalMonth_vector", fieldType, allocator);
+ NullableIntervalMonthDayNanoHolder holder1 = new NullableIntervalMonthDayNanoHolder();
+ NullableIntervalMonthDayNanoHolder holder2 = new NullableIntervalMonthDayNanoHolder();
+
+ holder1.days = 1;
+ holder1.months = 10;
+ holder1.isSet = 1;
+ holder2.days = 2;
+ holder2.months = 20;
+ holder2.isSet = 1;
+
+ vectors.add(intervalMonthVector);
+ intervalMonthVector.setSafe(0, holder1);
+ intervalMonthVector.setSafe(1, holder2);
+ intervalMonthVector.setValueCount(2);
+
+ PeriodDuration one = intervalMonthVector.getObject(1);
+ try (Table t = new Table(vectors)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertEquals(one, c.getIntervalMonthDayNanoObj("intervalMonth_vector"));
+ assertEquals(one, c.getIntervalMonthDayNanoObj(0));
+ c.getIntervalMonthDayNano(0, holder1);
+ c.getIntervalMonthDayNano("intervalMonth_vector", holder2);
+ assertEquals(holder1.days, holder2.days);
+ assertEquals(holder1.months, holder2.months);
+ ArrowBuf intMonthBuf1 = c.getIntervalMonthDayNano(0);
+ ArrowBuf intMonthBuf2 = c.getIntervalMonthDayNano("intervalMonth_vector");
+ assertEquals(intMonthBuf1.memoryAddress(), intMonthBuf2.memoryAddress());
+ }
+ }
+
+ @Test
+ void getIntervalYear() {
+ List vectors = new ArrayList<>();
+ IntervalUnit unit = IntervalUnit.YEAR_MONTH;
+ final FieldType fieldType = FieldType.nullable(new ArrowType.Interval(unit));
+
+ IntervalYearVector intervalYearVector = new IntervalYearVector("intervalYear_vector", fieldType, allocator);
+ NullableIntervalYearHolder holder1 = new NullableIntervalYearHolder();
+ NullableIntervalYearHolder holder2 = new NullableIntervalYearHolder();
+
+ holder1.value = 1;
+ holder1.isSet = 1;
+ holder2.value = 2;
+ holder2.isSet = 1;
+
+ vectors.add(intervalYearVector);
+ intervalYearVector.setSafe(0, holder1);
+ intervalYearVector.setSafe(1, holder2);
+ intervalYearVector.setValueCount(2);
+
+ Period one = intervalYearVector.getObject(1);
+ try (Table t = new Table(vectors)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertEquals(one, c.getIntervalYearObj("intervalYear_vector"));
+ assertEquals(one, c.getIntervalYearObj(0));
+ c.getIntervalYear(0, holder1);
+ c.getIntervalYear("intervalYear_vector", holder2);
+ assertEquals(holder1.value, holder2.value);
+ int intYear1 = c.getIntervalYear(0);
+ int intYear2 = c.getIntervalYear("intervalYear_vector");
+ assertEquals(2, intYear1);
+ assertEquals(intYear1, intYear2);
+ }
+ }
+
+ @Test
+ void getBit() {
+ List vectors = new ArrayList<>();
+
+ BitVector bitVector = new BitVector("bit_vector", allocator);
+ NullableBitHolder holder1 = new NullableBitHolder();
+ NullableBitHolder holder2 = new NullableBitHolder();
+
+ vectors.add(bitVector);
+ bitVector.setSafe(0, 0);
+ bitVector.setSafe(1, 1);
+ bitVector.setValueCount(2);
+
+ int one = bitVector.get(1);
+ try (Table t = new Table(vectors)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertEquals(one, c.getBit("bit_vector"));
+ assertEquals(one, c.getBit(0));
+ c.getBit(0, holder1);
+ c.getBit("bit_vector", holder2);
+ assertEquals(holder1.value, holder2.value);
+ }
+ }
+
+ @Test
+ void hasNext() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ assertTrue(c.hasNext());
+ c.setPosition(1);
+ assertFalse(c.hasNext());
+ }
+ }
+
+ @Test
+ void next() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(0);
+ c.next();
+ assertEquals(1, c.getRowNumber());
+ }
+ }
+
+ @Test
+ void isNull() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertFalse(c.isNull(0));
+ }
+ }
+
+ @Test
+ void isNullByFieldName() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertFalse(c.isNull(INT_VECTOR_NAME_1));
+ }
+ }
+
+ @Test
+ void fixedWidthVectorTest() {
+ List vectorList = fixedWidthVectors(allocator, 2);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ // integer tests using vector name and index
+ assertFalse(c.isNull("bigInt_vector"));
+ assertEquals(c.getInt("int_vector"), c.getInt(0));
+ assertEquals(c.getBigInt("bigInt_vector"), c.getBigInt(1));
+ assertEquals(c.getSmallInt("smallInt_vector"), c.getSmallInt(2));
+ assertEquals(c.getTinyInt("tinyInt_vector"), c.getTinyInt(3));
+
+ // integer tests using Nullable Holders
+ NullableIntHolder int4Holder = new NullableIntHolder();
+ NullableTinyIntHolder int1Holder = new NullableTinyIntHolder();
+ NullableSmallIntHolder int2Holder = new NullableSmallIntHolder();
+ NullableBigIntHolder int8Holder = new NullableBigIntHolder();
+ c.getInt(0, int4Holder);
+ c.getBigInt(1, int8Holder);
+ c.getSmallInt(2, int2Holder);
+ c.getTinyInt(3, int1Holder);
+ assertEquals(c.getInt("int_vector"), int4Holder.value);
+ assertEquals(c.getBigInt("bigInt_vector"), int8Holder.value);
+ assertEquals(c.getSmallInt("smallInt_vector"), int2Holder.value);
+ assertEquals(c.getTinyInt("tinyInt_vector"), int1Holder.value);
+
+ c.getInt("int_vector", int4Holder);
+ c.getBigInt("bigInt_vector", int8Holder);
+ c.getSmallInt("smallInt_vector", int2Holder);
+ c.getTinyInt("tinyInt_vector", int1Holder);
+ assertEquals(c.getInt("int_vector"), int4Holder.value);
+ assertEquals(c.getBigInt("bigInt_vector"), int8Holder.value);
+ assertEquals(c.getSmallInt("smallInt_vector"), int2Holder.value);
+ assertEquals(c.getTinyInt("tinyInt_vector"), int1Holder.value);
+
+ // uint tests using vector name and index
+ assertEquals(c.getUInt1("uInt1_vector"), c.getUInt1(4));
+ assertEquals(c.getUInt2("uInt2_vector"), c.getUInt2(5));
+ assertEquals(c.getUInt4("uInt4_vector"), c.getUInt4(6));
+ assertEquals(c.getUInt8("uInt8_vector"), c.getUInt8(7));
+
+ // UInt tests using Nullable Holders
+ NullableUInt4Holder uInt4Holder = new NullableUInt4Holder();
+ NullableUInt1Holder uInt1Holder = new NullableUInt1Holder();
+ NullableUInt2Holder uInt2Holder = new NullableUInt2Holder();
+ NullableUInt8Holder uInt8Holder = new NullableUInt8Holder();
+ // fill the holders using vector index and test
+ c.getUInt1(4, uInt1Holder);
+ c.getUInt2(5, uInt2Holder);
+ c.getUInt4(6, uInt4Holder);
+ c.getUInt8(7, uInt8Holder);
+ assertEquals(c.getUInt1("uInt1_vector"), uInt1Holder.value);
+ assertEquals(c.getUInt2("uInt2_vector"), uInt2Holder.value);
+ assertEquals(c.getUInt4("uInt4_vector"), uInt4Holder.value);
+ assertEquals(c.getUInt8("uInt8_vector"), uInt8Holder.value);
+
+ // refill the holders using vector name and retest
+ c.getUInt1("uInt1_vector", uInt1Holder);
+ c.getUInt2("uInt2_vector", uInt2Holder);
+ c.getUInt4("uInt4_vector", uInt4Holder);
+ c.getUInt8("uInt8_vector", uInt8Holder);
+ assertEquals(c.getUInt1("uInt1_vector"), uInt1Holder.value);
+ assertEquals(c.getUInt2("uInt2_vector"), uInt2Holder.value);
+ assertEquals(c.getUInt4("uInt4_vector"), uInt4Holder.value);
+ assertEquals(c.getUInt8("uInt8_vector"), uInt8Holder.value);
+
+ // tests floating point
+ assertEquals(c.getFloat4("float4_vector"), c.getFloat4(8));
+ assertEquals(c.getFloat8("float8_vector"), c.getFloat8(9));
+
+ // floating point tests using Nullable Holders
+ NullableFloat4Holder float4Holder = new NullableFloat4Holder();
+ NullableFloat8Holder float8Holder = new NullableFloat8Holder();
+ // fill the holders using vector index and test
+ c.getFloat4(8, float4Holder);
+ c.getFloat8(9, float8Holder);
+ assertEquals(c.getFloat4("float4_vector"), float4Holder.value);
+ assertEquals(c.getFloat8("float8_vector"), float8Holder.value);
+
+ // refill the holders using vector name and retest
+ c.getFloat4("float4_vector", float4Holder);
+ c.getFloat8("float8_vector", float8Holder);
+ assertEquals(c.getFloat4("float4_vector"), float4Holder.value);
+ assertEquals(c.getFloat8("float8_vector"), float8Holder.value);
+
+ // test time values using vector name versus vector index
+ assertEquals(c.getTimeSec("timeSec_vector"), c.getTimeSec(10));
+ assertEquals(c.getTimeMilli("timeMilli_vector"), c.getTimeMilli(11));
+ assertEquals(c.getTimeMicro("timeMicro_vector"), c.getTimeMicro(12));
+ assertEquals(c.getTimeNano("timeNano_vector"), c.getTimeNano(13));
+
+ // time tests using Nullable Holders
+ NullableTimeSecHolder timeSecHolder = new NullableTimeSecHolder();
+ NullableTimeMilliHolder timeMilliHolder = new NullableTimeMilliHolder();
+ NullableTimeMicroHolder timeMicroHolder = new NullableTimeMicroHolder();
+ NullableTimeNanoHolder timeNanoHolder = new NullableTimeNanoHolder();
+ // fill the holders using vector index and test
+ c.getTimeSec(10, timeSecHolder);
+ c.getTimeMilli(11, timeMilliHolder);
+ c.getTimeMicro(12, timeMicroHolder);
+ c.getTimeNano(13, timeNanoHolder);
+ assertEquals(c.getTimeSec("timeSec_vector"), timeSecHolder.value);
+ assertEquals(c.getTimeMilli("timeMilli_vector"), timeMilliHolder.value);
+ assertEquals(c.getTimeMicro("timeMicro_vector"), timeMicroHolder.value);
+ assertEquals(c.getTimeNano("timeNano_vector"), timeNanoHolder.value);
+
+ LocalDateTime milliDT = c.getTimeMilliObj(11);
+ assertNotNull(milliDT);
+ assertEquals(milliDT, c.getTimeMilliObj("timeMilli_vector"));
+
+ // refill the holders using vector name and retest
+ c.getTimeSec("timeSec_vector", timeSecHolder);
+ c.getTimeMilli("timeMilli_vector", timeMilliHolder);
+ c.getTimeMicro("timeMicro_vector", timeMicroHolder);
+ c.getTimeNano("timeNano_vector", timeNanoHolder);
+ assertEquals(c.getTimeSec("timeSec_vector"), timeSecHolder.value);
+ assertEquals(c.getTimeMilli("timeMilli_vector"), timeMilliHolder.value);
+ assertEquals(c.getTimeMicro("timeMicro_vector"), timeMicroHolder.value);
+ assertEquals(c.getTimeNano("timeNano_vector"), timeNanoHolder.value);
+
+ assertEquals(c.getTimeStampSec("timeStampSec_vector"), c.getTimeStampSec(14));
+ assertEquals(c.getTimeStampMilli("timeStampMilli_vector"), c.getTimeStampMilli(15));
+ assertEquals(c.getTimeStampMicro("timeStampMicro_vector"), c.getTimeStampMicro(16));
+ assertEquals(c.getTimeStampNano("timeStampNano_vector"), c.getTimeStampNano(17));
+
+ // time stamp tests using Nullable Holders
+ NullableTimeStampSecHolder timeStampSecHolder = new NullableTimeStampSecHolder();
+ NullableTimeStampMilliHolder timeStampMilliHolder = new NullableTimeStampMilliHolder();
+ NullableTimeStampMicroHolder timeStampMicroHolder = new NullableTimeStampMicroHolder();
+ NullableTimeStampNanoHolder timeStampNanoHolder = new NullableTimeStampNanoHolder();
+ // fill the holders using vector index and test
+ c.getTimeStampSec(14, timeStampSecHolder);
+ c.getTimeStampMilli(15, timeStampMilliHolder);
+ c.getTimeStampMicro(16, timeStampMicroHolder);
+ c.getTimeStampNano(17, timeStampNanoHolder);
+ assertEquals(c.getTimeStampSec("timeStampSec_vector"), timeStampSecHolder.value);
+ assertEquals(c.getTimeStampMilli("timeStampMilli_vector"), timeStampMilliHolder.value);
+ assertEquals(c.getTimeStampMicro("timeStampMicro_vector"), timeStampMicroHolder.value);
+ assertEquals(c.getTimeStampNano("timeStampNano_vector"), timeStampNanoHolder.value);
+
+ LocalDateTime secDT = c.getTimeStampSecObj(14);
+ assertNotNull(secDT);
+ assertEquals(secDT, c.getTimeStampSecObj("timeStampSec_vector"));
+
+ LocalDateTime milliDT1 = c.getTimeStampMilliObj(15);
+ assertNotNull(milliDT1);
+ assertEquals(milliDT1, c.getTimeStampMilliObj("timeStampMilli_vector"));
+
+ LocalDateTime microDT = c.getTimeStampMicroObj(16);
+ assertNotNull(microDT);
+ assertEquals(microDT, c.getTimeStampMicroObj("timeStampMicro_vector"));
+
+ LocalDateTime nanoDT = c.getTimeStampNanoObj(17);
+ assertNotNull(nanoDT);
+ assertEquals(nanoDT, c.getTimeStampNanoObj("timeStampNano_vector"));
+
+ // refill the holders using vector name and retest
+ c.getTimeStampSec("timeStampSec_vector", timeStampSecHolder);
+ c.getTimeStampMilli("timeStampMilli_vector", timeStampMilliHolder);
+ c.getTimeStampMicro("timeStampMicro_vector", timeStampMicroHolder);
+ c.getTimeStampNano("timeStampNano_vector", timeStampNanoHolder);
+ assertEquals(c.getTimeStampSec("timeStampSec_vector"), timeStampSecHolder.value);
+ assertEquals(c.getTimeStampMilli("timeStampMilli_vector"), timeStampMilliHolder.value);
+ assertEquals(c.getTimeStampMicro("timeStampMicro_vector"), timeStampMicroHolder.value);
+ assertEquals(c.getTimeStampNano("timeStampNano_vector"), timeStampNanoHolder.value);
+ }
+ }
+
+ @Test
+ void timestampsWithTimezones() {
+ List vectorList = timezoneTemporalVectors(allocator, 2);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+
+ assertEquals(c.getTimeStampSecTZ("timeStampSecTZ_vector"), c.getTimeStampSecTZ(0));
+ assertEquals(c.getTimeStampMilliTZ("timeStampMilliTZ_vector"), c.getTimeStampMilliTZ(1));
+ assertEquals(c.getTimeStampMicroTZ("timeStampMicroTZ_vector"), c.getTimeStampMicroTZ(2));
+ assertEquals(c.getTimeStampNanoTZ("timeStampNanoTZ_vector"), c.getTimeStampNanoTZ(3));
+
+ // time stamp tests using Nullable Holders
+ NullableTimeStampSecTZHolder timeStampSecHolder = new NullableTimeStampSecTZHolder();
+ NullableTimeStampMilliTZHolder timeStampMilliHolder = new NullableTimeStampMilliTZHolder();
+ NullableTimeStampMicroTZHolder timeStampMicroHolder = new NullableTimeStampMicroTZHolder();
+ NullableTimeStampNanoTZHolder timeStampNanoHolder = new NullableTimeStampNanoTZHolder();
+
+ // fill the holders using vector index and test
+ c.getTimeStampSecTZ(0, timeStampSecHolder);
+ c.getTimeStampMilliTZ(1, timeStampMilliHolder);
+ c.getTimeStampMicroTZ(2, timeStampMicroHolder);
+ c.getTimeStampNanoTZ(3, timeStampNanoHolder);
+
+ long tsSec = timeStampSecHolder.value;
+ long tsMil = timeStampMilliHolder.value;
+ long tsMic = timeStampMicroHolder.value;
+ long tsNan = timeStampNanoHolder.value;
+
+ assertEquals(c.getTimeStampSecTZ("timeStampSecTZ_vector"), timeStampSecHolder.value);
+ assertEquals(c.getTimeStampMilliTZ("timeStampMilliTZ_vector"), timeStampMilliHolder.value);
+ assertEquals(c.getTimeStampMicroTZ("timeStampMicroTZ_vector"), timeStampMicroHolder.value);
+ assertEquals(c.getTimeStampNanoTZ("timeStampNanoTZ_vector"), timeStampNanoHolder.value);
+
+ // fill the holders using vector index and test
+ c.getTimeStampSecTZ("timeStampSecTZ_vector", timeStampSecHolder);
+ c.getTimeStampMilliTZ("timeStampMilliTZ_vector", timeStampMilliHolder);
+ c.getTimeStampMicroTZ("timeStampMicroTZ_vector", timeStampMicroHolder);
+ c.getTimeStampNanoTZ("timeStampNanoTZ_vector", timeStampNanoHolder);
+
+ assertEquals(tsSec, timeStampSecHolder.value);
+ assertEquals(tsMil, timeStampMilliHolder.value);
+ assertEquals(tsMic, timeStampMicroHolder.value);
+ assertEquals(tsNan, timeStampNanoHolder.value);
+ }
+ }
+
+ @Test
+ void getVarChar() {
+ List vectorList = intPlusVarcharColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertEquals(c.getVarCharObj(1), "two");
+ assertEquals(c.getVarCharObj(1), c.getVarCharObj(VARCHAR_VECTOR_NAME_1));
+ assertArrayEquals("two".getBytes(), c.getVarChar(VARCHAR_VECTOR_NAME_1));
+ assertArrayEquals("two".getBytes(), c.getVarChar(1));
+ }
+ }
+
+ @Test
+ void getVarBinary() {
+ List vectorList = intPlusVarBinaryColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertArrayEquals(c.getVarBinary(1), "two".getBytes());
+ assertArrayEquals(c.getVarBinary(1), c.getVarBinary(VARBINARY_VECTOR_NAME_1));
+ }
+ }
+
+ @Test
+ void getLargeVarBinary() {
+ List vectorList = intPlusLargeVarBinaryColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertArrayEquals(c.getLargeVarBinary(1), "two".getBytes());
+ assertArrayEquals(c.getLargeVarBinary(1), c.getLargeVarBinary(VARBINARY_VECTOR_NAME_1));
+ }
+ }
+
+ @Test
+ void getLargeVarChar() {
+ List vectorList = intPlusLargeVarcharColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertEquals(c.getLargeVarCharObj(1), "two");
+ assertEquals(c.getLargeVarCharObj(1), c.getLargeVarCharObj(VARCHAR_VECTOR_NAME_1));
+ assertArrayEquals("two".getBytes(), c.getLargeVarChar(VARCHAR_VECTOR_NAME_1));
+ assertArrayEquals("two".getBytes(), c.getLargeVarChar(1));
+ }
+ }
+
+ @Test
+ void getFixedBinary() {
+ List vectorList = intPlusFixedBinaryColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Row c = t.immutableRow();
+ c.setPosition(1);
+ assertArrayEquals(c.getFixedSizeBinary(1), "two".getBytes());
+ assertArrayEquals(c.getFixedSizeBinary(1), c.getFixedSizeBinary(FIXEDBINARY_VECTOR_NAME_1));
+ }
+ }
+
+ @Test
+ void testSimpleListVector1() {
+ try (ListVector listVector = simpleListVector(allocator);
+ VectorSchemaRoot vectorSchemaRoot = VectorSchemaRoot.of(listVector);
+ Table table = new Table(vectorSchemaRoot)) {
+ for (Row c : table) {
+ @SuppressWarnings("unchecked")
+ List list = (List) c.getList(INT_LIST_VECTOR_NAME);
+ assertEquals(10, list.size());
+ }
+ }
+ }
+
+ @Test
+ void testSimpleListVector2() {
+ try (ListVector listVector = simpleListVector(allocator);
+ VectorSchemaRoot vectorSchemaRoot = VectorSchemaRoot.of(listVector);
+ Table table = new Table(vectorSchemaRoot)) {
+ for (Row c : table) {
+ @SuppressWarnings("unchecked")
+ List list = (List) c.getList(0);
+ assertEquals(10, list.size());
+ }
+ }
+ }
+
+ @Test
+ void testSimpleStructVector1() {
+ try (StructVector structVector = simpleStructVector(allocator);
+ VectorSchemaRoot vectorSchemaRoot = VectorSchemaRoot.of(structVector);
+ Table table = new Table(vectorSchemaRoot)) {
+ for (Row c : table) {
+ @SuppressWarnings("unchecked")
+ JsonStringHashMap struct =
+ (JsonStringHashMap) c.getStruct(STRUCT_VECTOR_NAME);
+ @SuppressWarnings("unchecked")
+ JsonStringHashMap struct1 =
+ (JsonStringHashMap) c.getStruct(0);
+ int a = (int) struct.get("struct_int_child");
+ double b = (double) struct.get("struct_flt_child");
+ int a1 = (int) struct1.get("struct_int_child");
+ double b1 = (double) struct1.get("struct_flt_child");
+ assertNotNull(struct);
+ assertEquals(a, a1);
+ assertEquals(b, b1);
+ assertTrue(a >= 0);
+ assertTrue(b <= a, String.format("a = %s and b = %s", a, b));
+ }
+ }
+ }
+
+ @Test
+ void testSimpleUnionVector() {
+ try (UnionVector unionVector = simpleUnionVector(allocator);
+ VectorSchemaRoot vsr = VectorSchemaRoot.of(unionVector);
+ Table table = new Table(vsr)) {
+ Row c = table.immutableRow();
+ c.setPosition(0);
+ Object object0 = c.getUnion(UNION_VECTOR_NAME);
+ Object object1 = c.getUnion(0);
+ assertEquals(object0, object1);
+ c.setPosition(1);
+ assertNull(c.getUnion(UNION_VECTOR_NAME));
+ c.setPosition(2);
+ Object object2 = c.getUnion(UNION_VECTOR_NAME);
+ assertEquals(100, object0);
+ assertEquals(100, object2);
+ }
+ }
+
+ @Test
+ void testSimpleDenseUnionVector() {
+ try (DenseUnionVector unionVector = simpleDenseUnionVector(allocator);
+ VectorSchemaRoot vsr = VectorSchemaRoot.of(unionVector);
+ Table table = new Table(vsr)) {
+ Row c = table.immutableRow();
+ c.setPosition(0);
+ Object object0 = c.getDenseUnion(UNION_VECTOR_NAME);
+ Object object1 = c.getDenseUnion(0);
+ assertEquals(object0, object1);
+ c.setPosition(1);
+ assertNull(c.getDenseUnion(UNION_VECTOR_NAME));
+ c.setPosition(2);
+ Object object2 = c.getDenseUnion(UNION_VECTOR_NAME);
+ assertEquals(100, object0);
+ assertEquals(100, object2);
+ }
+ }
+
+ @Test
+ void testExtensionTypeVector() {
+ TestExtensionType.LocationVector vector = new TestExtensionType.LocationVector("location", allocator);
+ vector.allocateNew();
+ vector.set(0, 34.073814f, -118.240784f);
+ vector.setValueCount(1);
+
+ try (VectorSchemaRoot vsr = VectorSchemaRoot.of(vector);
+ Table table = new Table(vsr)) {
+ Row c = table.immutableRow();
+ c.setPosition(0);
+ Object object0 = c.getExtensionType("location");
+ Object object1 = c.getExtensionType(0);
+ assertEquals(object0, object1);
+ @SuppressWarnings("unchecked")
+ JsonStringHashMap struct0 =
+ (JsonStringHashMap) object0;
+ assertEquals(34.073814f, struct0.get("Latitude"));
+ }
+ }
+
+ @Test
+ void testSimpleMapVector1() {
+ try (MapVector mapVector = simpleMapVector(allocator);
+ Table table = Table.of(mapVector)) {
+
+ int i = 1;
+ for (Row c : table) {
+ @SuppressWarnings("unchecked")
+ List> list =
+ (List>) c.getMap(BIGINT_INT_MAP_VECTOR_NAME);
+ @SuppressWarnings("unchecked")
+ List> list1 =
+ (List>) c.getMap(0);
+ for (int j = 0; j < list1.size(); j++) {
+ assertEquals(list.get(j), list1.get(j));
+ }
+ if (list != null && !list.isEmpty()) {
+ assertEquals(i, list.size());
+ for (JsonStringHashMap sv : list) {
+ assertEquals(2, sv.size());
+ Long o1 = (Long) sv.get("key");
+ Integer o2 = (Integer) sv.get("value");
+ assertEquals(o1, o2.longValue());
+ }
+ }
+ i++;
+ }
+ }
+ }
+
+ @Test
+ void resetPosition() {
+ try (ListVector listVector = simpleListVector(allocator);
+ VectorSchemaRoot vectorSchemaRoot = VectorSchemaRoot.of(listVector);
+ Table table = new Table(vectorSchemaRoot)) {
+ Row row = table.immutableRow();
+ row.next();
+ assertEquals(0, row.rowNumber);
+ row.resetPosition();
+ assertEquals(-1, row.rowNumber);
+ }
+ }
+}
diff --git a/java/vector/src/test/java/org/apache/arrow/vector/table/TableTest.java b/java/vector/src/test/java/org/apache/arrow/vector/table/TableTest.java
new file mode 100644
index 00000000000..ebbab4f57f8
--- /dev/null
+++ b/java/vector/src/test/java/org/apache/arrow/vector/table/TableTest.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.arrow.vector.table;
+
+import static org.apache.arrow.vector.table.TestUtils.INT_VECTOR_NAME_1;
+import static org.apache.arrow.vector.table.TestUtils.twoIntColumns;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.memory.RootAllocator;
+import org.apache.arrow.vector.FieldVector;
+import org.apache.arrow.vector.IntVector;
+import org.apache.arrow.vector.VectorSchemaRoot;
+import org.apache.arrow.vector.types.pojo.ArrowType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.types.pojo.Schema;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class TableTest {
+
+ private final ArrowType intArrowType = new ArrowType.Int(32, true);
+ private final FieldType intFieldType = new FieldType(true, intArrowType, null);
+
+ private BufferAllocator allocator;
+
+ @BeforeEach
+ public void init() {
+ allocator = new RootAllocator(Long.MAX_VALUE);
+ }
+
+ @Test
+ void of() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = Table.of(vectorList.toArray(new FieldVector[2]))) {
+ Row c = t.immutableRow();
+ assertEquals(2, t.getRowCount());
+ assertEquals(2, t.getVectorCount());
+ IntVector intVector1 = (IntVector) vectorList.get(0);
+ assertEquals(INT_VECTOR_NAME_1, intVector1.getName());
+ c.setPosition(0);
+
+ // Now test changes to the first vector
+ // first Table value is 1
+ assertEquals(1, c.getInt(INT_VECTOR_NAME_1));
+
+ // original vector is updated to set first value to 44
+ intVector1.setSafe(0, 44);
+ assertEquals(44, intVector1.get(0));
+
+ // first Table value is still 1 for the zeroth vector
+ assertEquals(1, c.getInt(0));
+ }
+ }
+
+ @Test
+ void constructor() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList, 2)) {
+ assertEquals(2, t.getRowCount());
+ assertEquals(2, t.getVectorCount());
+ Row c = t.immutableRow();
+ IntVector intVector1 = (IntVector) vectorList.get(0);
+ c.setPosition(0);
+
+ // Now test changes to the first vector
+ // first Table value is 1
+ assertEquals(1, c.getInt(INT_VECTOR_NAME_1));
+
+ // original vector is updated to set first value to 44
+ intVector1.setSafe(0, 44);
+ assertEquals(44, intVector1.get(0));
+ assertEquals(44, ((IntVector) vectorList.get(0)).get(0));
+
+ // first Table value is still 1 for the zeroth vector
+ assertEquals(1, c.getInt(INT_VECTOR_NAME_1));
+ }
+ }
+
+ /**
+ * Tests construction with an iterable that's not a list (there is a specialty constructor for Lists).
+ */
+ @Test
+ void constructor2() {
+ List vectorList = twoIntColumns(allocator);
+ Iterable iterable = new HashSet<>(vectorList);
+ try (Table t = new Table(iterable)) {
+ assertEquals(2, t.getRowCount());
+ assertEquals(2, t.getVectorCount());
+ Row c = t.immutableRow();
+ IntVector intVector1 = (IntVector) vectorList.get(0);
+ c.setPosition(0);
+
+ // Now test changes to the first vector
+ // first Table value is 1
+ assertEquals(1, c.getInt(INT_VECTOR_NAME_1));
+
+ // original vector is updated to set first value to 44
+ intVector1.setSafe(0, 44);
+ assertEquals(44, intVector1.get(0));
+ assertEquals(44, ((IntVector) vectorList.get(0)).get(0));
+
+ // first Table value is still 1 for the zeroth vector
+ assertEquals(1, c.getInt(INT_VECTOR_NAME_1));
+ }
+ }
+
+ @Test
+ void addVector() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ IntVector v3 = new IntVector("3", intFieldType, allocator);
+ Table t2 = t.addVector(2, v3);
+ assertEquals(3, t2.fieldVectors.size());
+ assertTrue(t2.getVector("3").isNull(0));
+ assertTrue(t2.getVector("3").isNull(1));
+ t2.close();
+ }
+ }
+
+ @Test
+ void removeVector() {
+ List vectorList = twoIntColumns(allocator);
+ IntVector v2 = (IntVector) vectorList.get(1);
+ int val1 = v2.get(0);
+ int val2 = v2.get(1);
+ try (Table t = new Table(vectorList)) {
+
+ Table t2 = t.removeVector(0);
+ assertEquals(1, t2.fieldVectors.size());
+ assertEquals(val1, ((IntVector) t2.getVector(0)).get(0));
+ assertEquals(val2, ((IntVector) t2.getVector(0)).get(1));
+ }
+ }
+
+ /** Tests table iterator in enhanced for loop. */
+ @Test
+ void iterator1() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Iterator iterator = t.iterator();
+ assertNotNull(iterator);
+ assertTrue(iterator.hasNext());
+ int sum = 0;
+ for (Row row : t) {
+ sum += row.getInt(0);
+ }
+ assertEquals(3, sum);
+ }
+ }
+
+ /** Tests explicit iterator. */
+ @SuppressWarnings("WhileLoopReplaceableByForEach")
+ @Test
+ void iterator2() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Iterator iterator = t.iterator();
+ assertNotNull(iterator);
+ assertTrue(iterator.hasNext());
+ int sum = 0;
+ Iterator it = t.iterator();
+ while (it.hasNext()) {
+ Row row = it.next();
+ sum += row.getInt(0);
+ }
+ assertEquals(3, sum);
+ }
+ }
+
+ /**
+ * Tests a slice operation where no length is provided, so the range extends to the end of the
+ * table.
+ */
+ @Test
+ void sliceToEnd() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Table slice = t.slice(1);
+ assertEquals(1, slice.rowCount);
+ assertEquals(2, t.rowCount); // memory is copied for slice, not transferred
+ slice.close();
+ }
+ }
+
+ /** Tests a slice operation with a given length parameter. */
+ @Test
+ void sliceRange() {
+ List vectorList = twoIntColumns(allocator);
+ try (Table t = new Table(vectorList)) {
+ Table slice = t.slice(1, 1);
+ assertEquals(1, slice.rowCount);
+ assertEquals(2, t.rowCount); // memory is copied for slice, not transferred
+ slice.close();
+ }
+ }
+
+ /**
+ * Tests creation of a table from a VectorSchemaRoot.
+ *
+ * Also tests that updates to the source Vectors do not impact the values in the Table
+ */
+ @Test
+ void constructFromVsr() {
+ List vectorList = twoIntColumns(allocator);
+ try (VectorSchemaRoot vsr = new VectorSchemaRoot(vectorList)) {
+ Table t = new Table(vsr);
+ Row c = t.immutableRow();
+ assertEquals(2, t.rowCount);
+ assertEquals(0, vsr.getRowCount()); // memory is copied for slice, not transferred
+ IntVector intVector1 = (IntVector) vectorList.get(0);
+ c.setPosition(0);
+
+ // Now test changes to the first vector
+ // first Table value is 1
+ assertEquals(1, c.getInt(INT_VECTOR_NAME_1));
+
+ // original vector is updated to set first value to 44
+ intVector1.setSafe(0, 44);
+ assertEquals(44, intVector1.get(0));
+ assertEquals(44, ((IntVector) vsr.getVector(0)).get(0));
+
+ // first Table value is still 1 for the zeroth vector
+ assertEquals(1, c.getInt(INT_VECTOR_NAME_1));
+
+ // TEST FIELDS //
+ Schema schema = t.schema;
+ Field f1 = t.getField(INT_VECTOR_NAME_1);
+ FieldVector fv1 = vectorList.get(0);
+ assertEquals(f1, fv1.getField());
+ assertEquals(f1, schema.findField(INT_VECTOR_NAME_1));
+ t.close();
+ }
+ }
+}
diff --git a/java/vector/src/test/java/org/apache/arrow/vector/table/TestUtils.java b/java/vector/src/test/java/org/apache/arrow/vector/table/TestUtils.java
new file mode 100644
index 00000000000..b64f8b1a057
--- /dev/null
+++ b/java/vector/src/test/java/org/apache/arrow/vector/table/TestUtils.java
@@ -0,0 +1,383 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.arrow.vector.table;
+
+import static org.apache.arrow.vector.complex.BaseRepeatedValueVector.OFFSET_WIDTH;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.BigIntVector;
+import org.apache.arrow.vector.BitVectorHelper;
+import org.apache.arrow.vector.FieldVector;
+import org.apache.arrow.vector.FixedSizeBinaryVector;
+import org.apache.arrow.vector.Float4Vector;
+import org.apache.arrow.vector.Float8Vector;
+import org.apache.arrow.vector.GenerateSampleData;
+import org.apache.arrow.vector.IntVector;
+import org.apache.arrow.vector.LargeVarBinaryVector;
+import org.apache.arrow.vector.LargeVarCharVector;
+import org.apache.arrow.vector.SmallIntVector;
+import org.apache.arrow.vector.TimeMicroVector;
+import org.apache.arrow.vector.TimeMilliVector;
+import org.apache.arrow.vector.TimeNanoVector;
+import org.apache.arrow.vector.TimeSecVector;
+import org.apache.arrow.vector.TimeStampMicroTZVector;
+import org.apache.arrow.vector.TimeStampMicroVector;
+import org.apache.arrow.vector.TimeStampMilliTZVector;
+import org.apache.arrow.vector.TimeStampMilliVector;
+import org.apache.arrow.vector.TimeStampNanoTZVector;
+import org.apache.arrow.vector.TimeStampNanoVector;
+import org.apache.arrow.vector.TimeStampSecTZVector;
+import org.apache.arrow.vector.TimeStampSecVector;
+import org.apache.arrow.vector.TinyIntVector;
+import org.apache.arrow.vector.UInt1Vector;
+import org.apache.arrow.vector.UInt2Vector;
+import org.apache.arrow.vector.UInt4Vector;
+import org.apache.arrow.vector.UInt8Vector;
+import org.apache.arrow.vector.VarBinaryVector;
+import org.apache.arrow.vector.VarCharVector;
+import org.apache.arrow.vector.complex.DenseUnionVector;
+import org.apache.arrow.vector.complex.ListVector;
+import org.apache.arrow.vector.complex.MapVector;
+import org.apache.arrow.vector.complex.StructVector;
+import org.apache.arrow.vector.complex.UnionVector;
+import org.apache.arrow.vector.complex.impl.NullableStructWriter;
+import org.apache.arrow.vector.complex.impl.UnionMapWriter;
+import org.apache.arrow.vector.complex.writer.Float8Writer;
+import org.apache.arrow.vector.complex.writer.IntWriter;
+import org.apache.arrow.vector.holders.NullableUInt4Holder;
+import org.apache.arrow.vector.types.Types;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+
+public class TestUtils {
+
+ public static final String INT_VECTOR_NAME = "intCol";
+ public static final String INT_VECTOR_NAME_1 = "intCol1";
+ public static final String VARCHAR_VECTOR_NAME_1 = "varcharCol1";
+ public static final String VARBINARY_VECTOR_NAME_1 = "varbinaryCol1";
+ public static final String FIXEDBINARY_VECTOR_NAME_1 = "varbinaryCol1";
+ public static final String INT_VECTOR_NAME_2 = "intCol2";
+ public static final String INT_LIST_VECTOR_NAME = "int list vector";
+ public static final String BIGINT_INT_MAP_VECTOR_NAME = "bigint-int map vector";
+ public static final String STRUCT_VECTOR_NAME = "struct_vector";
+ public static final String UNION_VECTOR_NAME = "union_vector";
+
+ /**
+ * Returns a list of two IntVectors to be used to instantiate Tables for testing. Each IntVector
+ * has two values set.
+ */
+ static List twoIntColumns(BufferAllocator allocator) {
+ List vectorList = new ArrayList<>();
+ IntVector v1 = getSimpleIntVector(allocator);
+ IntVector v2 = new IntVector(INT_VECTOR_NAME_2, allocator);
+ v2.allocateNew(2);
+ v2.set(0, 3);
+ v2.set(1, 4);
+ v2.setValueCount(2);
+ vectorList.add(v1);
+ vectorList.add(v2);
+ return vectorList;
+ }
+
+ /**
+ * Returns a list of two FieldVectors to be used to instantiate Tables for testing. The first
+ * vector is an IntVector and the second is a VarCharVector. Each vector has two values set.
+ */
+ static List intPlusVarcharColumns(BufferAllocator allocator) {
+ List vectorList = new ArrayList<>();
+ IntVector v1 = getSimpleIntVector(allocator);
+ VarCharVector v2 = new VarCharVector(VARCHAR_VECTOR_NAME_1, allocator);
+ v2.allocateNew(2);
+ v2.set(0, "one".getBytes());
+ v2.set(1, "two".getBytes());
+ v2.setValueCount(2);
+ vectorList.add(v1);
+ vectorList.add(v2);
+ return vectorList;
+ }
+
+ /**
+ * Returns a list of two FieldVectors to be used to instantiate Tables for testing. The first
+ * vector is an IntVector and the second is a LargeVarCharVector. Each vector has two values set.
+ */
+ static List intPlusLargeVarcharColumns(BufferAllocator allocator) {
+ List vectorList = new ArrayList<>();
+ IntVector v1 = getSimpleIntVector(allocator);
+ LargeVarCharVector v2 = new LargeVarCharVector(VARCHAR_VECTOR_NAME_1, allocator);
+ v2.allocateNew(2);
+ v2.set(0, "one".getBytes());
+ v2.set(1, "two".getBytes());
+ v2.setValueCount(2);
+ vectorList.add(v1);
+ vectorList.add(v2);
+ return vectorList;
+ }
+
+ /**
+ * Returns a list of two FieldVectors to be used to instantiate Tables for testing. The first
+ * vector is an IntVector and the second is a VarBinaryVector. Each vector has two values set.
+ * The large binary vectors values are "one" and "two" encoded with UTF-8
+ */
+ static List intPlusVarBinaryColumns(BufferAllocator allocator) {
+ List vectorList = new ArrayList<>();
+ IntVector v1 = getSimpleIntVector(allocator);
+ VarBinaryVector v2 = new VarBinaryVector(VARBINARY_VECTOR_NAME_1, allocator);
+ v2.allocateNew(2);
+ v2.set(0, "one".getBytes());
+ v2.set(1, "two".getBytes());
+ v2.setValueCount(2);
+ vectorList.add(v1);
+ vectorList.add(v2);
+ return vectorList;
+ }
+
+ /**
+ * Returns a list of two FieldVectors to be used to instantiate Tables for testing. The first
+ * vector is an IntVector and the second is a VarBinaryVector. Each vector has two values set.
+ * The large binary vectors values are "one" and "two" encoded with UTF-8
+ */
+ static List intPlusLargeVarBinaryColumns(BufferAllocator allocator) {
+ List vectorList = new ArrayList<>();
+ IntVector v1 = getSimpleIntVector(allocator);
+ LargeVarBinaryVector v2 = new LargeVarBinaryVector(VARBINARY_VECTOR_NAME_1, allocator);
+ v2.allocateNew(2);
+ v2.set(0, "one".getBytes());
+ v2.set(1, "two".getBytes());
+ v2.setValueCount(2);
+ vectorList.add(v1);
+ vectorList.add(v2);
+ return vectorList;
+ }
+
+ /**
+ * Returns a list of two FieldVectors to be used to instantiate Tables for testing. The first
+ * vector is an IntVector and the second is a FixedSizeBinary vector. Each vector has two values set.
+ * The large binary vectors values are "one" and "two" encoded with UTF-8
+ */
+ static List intPlusFixedBinaryColumns(BufferAllocator allocator) {
+ List vectorList = new ArrayList<>();
+ IntVector v1 = getSimpleIntVector(allocator);
+ FixedSizeBinaryVector v2 = new FixedSizeBinaryVector(FIXEDBINARY_VECTOR_NAME_1, allocator, 3);
+ v2.allocateNew(2);
+ v2.set(0, "one".getBytes());
+ v2.set(1, "two".getBytes());
+ v2.setValueCount(2);
+ vectorList.add(v1);
+ vectorList.add(v2);
+ return vectorList;
+ }
+
+ private static IntVector getSimpleIntVector(BufferAllocator allocator) {
+ IntVector v1 = new IntVector(INT_VECTOR_NAME_1, allocator);
+ v1.allocateNew(2);
+ v1.set(0, 1);
+ v1.set(1, 2);
+ v1.setValueCount(2);
+ return v1;
+ }
+
+ /**
+ * Returns a list of fixed-width vectors for testing. It includes
+ *
+ * all integral and floating point types
+ * all basic times and timestamps (second, milli, micro, nano
+ *
+ *
+ * The vector names are based on their type name (e.g. BigIntVector is called "bigInt_vector"
+ */
+ static List fixedWidthVectors(BufferAllocator allocator, int rowCount) {
+ List vectors = new ArrayList<>();
+ numericVectors(vectors, allocator, rowCount);
+ simpleTemporalVectors(vectors, allocator, rowCount);
+ return vectors;
+ }
+
+ /**
+ * Returns a list of all integral and floating point vectors.
+ * The vector names are based on their type name (e.g. BigIntVector is called "bigInt_vector"
+ */
+ static List numericVectors(
+ List vectors, BufferAllocator allocator, int rowCount) {
+ vectors.add(new IntVector("int_vector", allocator));
+ vectors.add(new BigIntVector("bigInt_vector", allocator));
+ vectors.add(new SmallIntVector("smallInt_vector", allocator));
+ vectors.add(new TinyIntVector("tinyInt_vector", allocator));
+ vectors.add(new UInt1Vector("uInt1_vector", allocator));
+ vectors.add(new UInt2Vector("uInt2_vector", allocator));
+ vectors.add(new UInt4Vector("uInt4_vector", allocator));
+ vectors.add(new UInt8Vector("uInt8_vector", allocator));
+ vectors.add(new Float4Vector("float4_vector", allocator));
+ vectors.add(new Float8Vector("float8_vector", allocator));
+ vectors.forEach(vec -> GenerateSampleData.generateTestData(vec, rowCount));
+ return vectors;
+ }
+
+ static List numericVectors(BufferAllocator allocator, int rowCount) {
+ List vectors = new ArrayList<>();
+ return numericVectors(vectors, allocator, rowCount);
+ }
+
+ static List simpleTemporalVectors(
+ List vectors, BufferAllocator allocator, int rowCount) {
+ vectors.add(new TimeSecVector("timeSec_vector", allocator));
+ vectors.add(new TimeMilliVector("timeMilli_vector", allocator));
+ vectors.add(new TimeMicroVector("timeMicro_vector", allocator));
+ vectors.add(new TimeNanoVector("timeNano_vector", allocator));
+
+ vectors.add(new TimeStampSecVector("timeStampSec_vector", allocator));
+ vectors.add(new TimeStampMilliVector("timeStampMilli_vector", allocator));
+ vectors.add(new TimeStampMicroVector("timeStampMicro_vector", allocator));
+ vectors.add(new TimeStampNanoVector("timeStampNano_vector", allocator));
+
+ vectors.forEach(vec -> GenerateSampleData.generateTestData(vec, rowCount));
+ return vectors;
+ }
+
+ static List simpleTemporalVectors(BufferAllocator allocator, int rowCount) {
+ List vectors = new ArrayList<>();
+ return simpleTemporalVectors(vectors, allocator, rowCount);
+ }
+
+ static List timezoneTemporalVectors(BufferAllocator allocator, int rowCount) {
+ List vectors = new ArrayList<>();
+ vectors.add(new TimeStampSecTZVector("timeStampSecTZ_vector", allocator, "UTC"));
+ vectors.add(new TimeStampMilliTZVector("timeStampMilliTZ_vector", allocator, "UTC"));
+ vectors.add(new TimeStampMicroTZVector("timeStampMicroTZ_vector", allocator, "UTC"));
+ vectors.add(new TimeStampNanoTZVector("timeStampNanoTZ_vector", allocator, "UTC"));
+ vectors.forEach(vec -> GenerateSampleData.generateTestData(vec, rowCount));
+ return vectors;
+ }
+
+ /** Returns a list vector of ints. */
+ static ListVector simpleListVector(BufferAllocator allocator) {
+ ListVector listVector = ListVector.empty(INT_LIST_VECTOR_NAME, allocator);
+ final int innerCount = 80; // total number of values
+ final int outerCount = 8; // total number of values in the list vector itself
+ final int listLength = innerCount / outerCount; // length of an individual list
+
+ Types.MinorType type = Types.MinorType.INT;
+ listVector.addOrGetVector(FieldType.nullable(type.getType()));
+
+ listVector.allocateNew();
+ IntVector dataVector = (IntVector) listVector.getDataVector();
+
+ for (int i = 0; i < innerCount; i++) {
+ dataVector.set(i, i);
+ }
+ dataVector.setValueCount(innerCount);
+
+ for (int i = 0; i < outerCount; i++) {
+ BitVectorHelper.setBit(listVector.getValidityBuffer(), i);
+ listVector.getOffsetBuffer().setInt(i * OFFSET_WIDTH, i * listLength);
+ listVector.getOffsetBuffer().setInt((i + 1) * OFFSET_WIDTH, (i + 1) * listLength);
+ }
+ listVector.setLastSet(outerCount - 1);
+ listVector.setValueCount(outerCount);
+
+ return listVector;
+ }
+
+ static StructVector simpleStructVector(BufferAllocator allocator) {
+ final String INT_COL = "struct_int_child";
+ final String FLT_COL = "struct_flt_child";
+ StructVector structVector = StructVector.empty(STRUCT_VECTOR_NAME, allocator);
+ final int size = 6; // number of structs
+
+ NullableStructWriter structWriter = structVector.getWriter();
+ structVector.addOrGet(
+ INT_COL, FieldType.nullable(Types.MinorType.INT.getType()), IntVector.class);
+ structVector.addOrGet(
+ FLT_COL, FieldType.nullable(Types.MinorType.INT.getType()), IntVector.class);
+ structVector.allocateNew();
+ IntWriter intWriter = structWriter.integer(INT_COL);
+ Float8Writer float8Writer = structWriter.float8(FLT_COL);
+
+ for (int i = 0; i < size; i++) {
+ structWriter.setPosition(i);
+ structWriter.start();
+ intWriter.writeInt(i);
+ float8Writer.writeFloat8(i * .1);
+ structWriter.end();
+ }
+
+ structWriter.setValueCount(size);
+
+ return structVector;
+ }
+
+ /** Returns a MapVector of ints to doubles. */
+ static MapVector simpleMapVector(BufferAllocator allocator) {
+ MapVector mapVector = MapVector.empty(BIGINT_INT_MAP_VECTOR_NAME, allocator, false);
+ mapVector.allocateNew();
+ int count = 5;
+ UnionMapWriter mapWriter = mapVector.getWriter();
+ for (int i = 0; i < count; i++) {
+ mapWriter.startMap();
+ for (int j = 0; j < i + 1; j++) {
+ mapWriter.startEntry();
+ mapWriter.key().bigInt().writeBigInt(j);
+ mapWriter.value().integer().writeInt(j);
+ mapWriter.endEntry();
+ }
+ mapWriter.endMap();
+ }
+ mapWriter.setValueCount(count);
+ return mapVector;
+ }
+
+ /** Returns a UnionVector. */
+ static UnionVector simpleUnionVector(BufferAllocator allocator) {
+ final NullableUInt4Holder uInt4Holder = new NullableUInt4Holder();
+ uInt4Holder.value = 100;
+ uInt4Holder.isSet = 1;
+
+ UnionVector unionVector = new UnionVector(UNION_VECTOR_NAME, allocator, null, null);
+ unionVector.allocateNew();
+
+ // write some data
+ unionVector.setType(0, Types.MinorType.UINT4);
+ unionVector.setSafe(0, uInt4Holder);
+ unionVector.setType(2, Types.MinorType.UINT4);
+ unionVector.setSafe(2, uInt4Holder);
+ unionVector.setValueCount(4);
+ return unionVector;
+ }
+
+ /** Returns a DenseUnionVector. */
+ static DenseUnionVector simpleDenseUnionVector(BufferAllocator allocator) {
+ final NullableUInt4Holder uInt4Holder = new NullableUInt4Holder();
+ uInt4Holder.value = 100;
+ uInt4Holder.isSet = 1;
+
+ DenseUnionVector unionVector = new DenseUnionVector(UNION_VECTOR_NAME, allocator, null, null);
+ unionVector.allocateNew();
+
+ // write some data
+ byte uint4TypeId =
+ unionVector.registerNewTypeId(Field.nullable("", Types.MinorType.UINT4.getType()));
+ unionVector.setTypeId(0, uint4TypeId);
+ unionVector.setSafe(0, uInt4Holder);
+ unionVector.setTypeId(2, uint4TypeId);
+ unionVector.setSafe(2, uInt4Holder);
+ unionVector.setValueCount(4);
+ return unionVector;
+ }
+}
diff --git a/java/vector/src/test/java/org/apache/arrow/vector/types/pojo/TestExtensionType.java b/java/vector/src/test/java/org/apache/arrow/vector/types/pojo/TestExtensionType.java
index 8b2743210de..1b3d5eee35f 100644
--- a/java/vector/src/test/java/org/apache/arrow/vector/types/pojo/TestExtensionType.java
+++ b/java/vector/src/test/java/org/apache/arrow/vector/types/pojo/TestExtensionType.java
@@ -380,7 +380,7 @@ public FieldVector getNewVector(String name, FieldType fieldType, BufferAllocato
}
}
- static class LocationVector extends ExtensionTypeVector {
+ public static class LocationVector extends ExtensionTypeVector {
private static StructVector buildUnderlyingVector(String name, BufferAllocator allocator) {
final StructVector underlyingVector =