This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 8068554a5d GH-43512: [Java] ListViewVector Visitor-based component
Integration (#43513)
8068554a5d is described below
commit 8068554a5d18129121f824978c7ee4a9c430640b
Author: Vibhatha Lakmal Abeykoon <[email protected]>
AuthorDate: Fri Aug 2 06:34:34 2024 +0530
GH-43512: [Java] ListViewVector Visitor-based component Integration (#43513)
### Rationale for this change
This PR integrates the core visitor-based components to ListViewVector.
### What changes are included in this PR?
This PR includes the addition of `RangeEqualsVisitor`, `TypeEqualsVisitor`
and necessary test cases.
### Are these changes tested?
Yes
### Are there any user-facing changes?
No
* GitHub Issue: #43512
Authored-by: Vibhatha Abeykoon <[email protected]>
Signed-off-by: David Li <[email protected]>
---
.../arrow/vector/compare/RangeEqualsVisitor.java | 57 ++++++++++++
.../arrow/vector/compare/TypeEqualsVisitor.java | 6 ++
.../apache/arrow/vector/compare/VectorVisitor.java | 5 ++
.../arrow/vector/complex/ListViewVector.java | 2 +-
.../org/apache/arrow/vector/TestValueVector.java | 60 +++++++++++++
.../vector/compare/TestRangeEqualsVisitor.java | 100 +++++++++++++++++++++
.../vector/compare/TestTypeEqualsVisitor.java | 17 ++++
7 files changed, 246 insertions(+), 1 deletion(-)
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/compare/RangeEqualsVisitor.java
b/java/vector/src/main/java/org/apache/arrow/vector/compare/RangeEqualsVisitor.java
index 3050649737..fbc28a3609 100644
---
a/java/vector/src/main/java/org/apache/arrow/vector/compare/RangeEqualsVisitor.java
+++
b/java/vector/src/main/java/org/apache/arrow/vector/compare/RangeEqualsVisitor.java
@@ -32,10 +32,12 @@ import org.apache.arrow.vector.ExtensionTypeVector;
import org.apache.arrow.vector.NullVector;
import org.apache.arrow.vector.ValueVector;
import org.apache.arrow.vector.complex.BaseRepeatedValueVector;
+import org.apache.arrow.vector.complex.BaseRepeatedValueViewVector;
import org.apache.arrow.vector.complex.DenseUnionVector;
import org.apache.arrow.vector.complex.FixedSizeListVector;
import org.apache.arrow.vector.complex.LargeListVector;
import org.apache.arrow.vector.complex.ListVector;
+import org.apache.arrow.vector.complex.ListViewVector;
import org.apache.arrow.vector.complex.NonNullableStructVector;
import org.apache.arrow.vector.complex.UnionVector;
@@ -234,6 +236,14 @@ public class RangeEqualsVisitor implements
VectorVisitor<Boolean, Range> {
return underlyingVisitor.rangeEquals(range);
}
+ @Override
+ public Boolean visit(ListViewVector left, Range range) {
+ if (!validate(left)) {
+ return false;
+ }
+ return compareListViewVectors(range);
+ }
+
protected RangeEqualsVisitor createInnerVisitor(
ValueVector leftInner,
ValueVector rightInner,
@@ -702,4 +712,51 @@ public class RangeEqualsVisitor implements
VectorVisitor<Boolean, Range> {
}
return true;
}
+
+ protected boolean compareListViewVectors(Range range) {
+ ListViewVector leftVector = (ListViewVector) left;
+ ListViewVector rightVector = (ListViewVector) right;
+
+ RangeEqualsVisitor innerVisitor =
+ createInnerVisitor(
+ leftVector.getDataVector(), rightVector.getDataVector(), /*type
comparator*/ null);
+ Range innerRange = new Range();
+
+ for (int i = 0; i < range.getLength(); i++) {
+ int leftIndex = range.getLeftStart() + i;
+ int rightIndex = range.getRightStart() + i;
+
+ boolean isNull = leftVector.isNull(leftIndex);
+ if (isNull != rightVector.isNull(rightIndex)) {
+ return false;
+ }
+
+ int offsetWidth = BaseRepeatedValueViewVector.OFFSET_WIDTH;
+ int sizeWidth = BaseRepeatedValueViewVector.SIZE_WIDTH;
+
+ if (!isNull) {
+ final int startIndexLeft =
+ leftVector.getOffsetBuffer().getInt((long) leftIndex *
offsetWidth);
+ final int leftSize = leftVector.getSizeBuffer().getInt((long)
leftIndex * sizeWidth);
+
+ final int startIndexRight =
+ rightVector.getOffsetBuffer().getInt((long) rightIndex *
offsetWidth);
+ final int rightSize = rightVector.getSizeBuffer().getInt((long)
rightIndex * sizeWidth);
+
+ if (leftSize != rightSize) {
+ return false;
+ }
+
+ innerRange =
+ innerRange
+ .setRightStart(startIndexRight)
+ .setLeftStart(startIndexLeft)
+ .setLength(leftSize);
+ if (!innerVisitor.rangeEquals(innerRange)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/compare/TypeEqualsVisitor.java
b/java/vector/src/main/java/org/apache/arrow/vector/compare/TypeEqualsVisitor.java
index 15cc2c31b8..6e15d6a83e 100644
---
a/java/vector/src/main/java/org/apache/arrow/vector/compare/TypeEqualsVisitor.java
+++
b/java/vector/src/main/java/org/apache/arrow/vector/compare/TypeEqualsVisitor.java
@@ -29,6 +29,7 @@ import org.apache.arrow.vector.complex.DenseUnionVector;
import org.apache.arrow.vector.complex.FixedSizeListVector;
import org.apache.arrow.vector.complex.LargeListVector;
import org.apache.arrow.vector.complex.ListVector;
+import org.apache.arrow.vector.complex.ListViewVector;
import org.apache.arrow.vector.complex.NonNullableStructVector;
import org.apache.arrow.vector.complex.UnionVector;
import org.apache.arrow.vector.types.pojo.Field;
@@ -124,6 +125,11 @@ public class TypeEqualsVisitor implements
VectorVisitor<Boolean, Void> {
return compareField(left.getField(), right.getField());
}
+ @Override
+ public Boolean visit(ListViewVector left, Void value) {
+ return compareField(left.getField(), right.getField());
+ }
+
private boolean compareField(Field leftField, Field rightField) {
if (leftField == rightField) {
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/compare/VectorVisitor.java
b/java/vector/src/main/java/org/apache/arrow/vector/compare/VectorVisitor.java
index 870f015862..c912359d4a 100644
---
a/java/vector/src/main/java/org/apache/arrow/vector/compare/VectorVisitor.java
+++
b/java/vector/src/main/java/org/apache/arrow/vector/compare/VectorVisitor.java
@@ -26,6 +26,7 @@ import org.apache.arrow.vector.complex.DenseUnionVector;
import org.apache.arrow.vector.complex.FixedSizeListVector;
import org.apache.arrow.vector.complex.LargeListVector;
import org.apache.arrow.vector.complex.ListVector;
+import org.apache.arrow.vector.complex.ListViewVector;
import org.apache.arrow.vector.complex.NonNullableStructVector;
import org.apache.arrow.vector.complex.UnionVector;
@@ -60,4 +61,8 @@ public interface VectorVisitor<OUT, IN> {
OUT visit(NullVector left, IN value);
OUT visit(ExtensionTypeVector<?> left, IN value);
+
+ default OUT visit(ListViewVector left, IN value) {
+ throw new UnsupportedOperationException("VectorVisitor for ListViewVector
is not supported.");
+ }
}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/complex/ListViewVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/complex/ListViewVector.java
index d719c9b1a9..6ced66d81e 100644
---
a/java/vector/src/main/java/org/apache/arrow/vector/complex/ListViewVector.java
+++
b/java/vector/src/main/java/org/apache/arrow/vector/complex/ListViewVector.java
@@ -341,7 +341,7 @@ public class ListViewVector extends
BaseRepeatedValueViewVector
@Override
public <OUT, IN> OUT accept(VectorVisitor<OUT, IN> visitor, IN value) {
- throw new UnsupportedOperationException("ListViewVector does not support
visitor pattern.");
+ return visitor.visit(this, value);
}
@Override
diff --git
a/java/vector/src/test/java/org/apache/arrow/vector/TestValueVector.java
b/java/vector/src/test/java/org/apache/arrow/vector/TestValueVector.java
index 376ad3ec75..4dd55afdb8 100644
--- a/java/vector/src/test/java/org/apache/arrow/vector/TestValueVector.java
+++ b/java/vector/src/test/java/org/apache/arrow/vector/TestValueVector.java
@@ -2882,6 +2882,34 @@ public class TestValueVector {
}
}
+ @Test
+ public void testListViewVectorEqualsWithNull() {
+ try (final ListViewVector vector1 = ListViewVector.empty("listview",
allocator);
+ final ListViewVector vector2 = ListViewVector.empty("listview",
allocator); ) {
+
+ UnionListViewWriter writer1 = vector1.getWriter();
+ writer1.allocate();
+
+ // set some values
+ writeListViewVector(writer1, new int[] {1, 2});
+ writeListViewVector(writer1, new int[] {3, 4});
+ writeListViewVector(writer1, new int[] {});
+ writer1.setValueCount(3);
+
+ UnionListViewWriter writer2 = vector2.getWriter();
+ writer2.allocate();
+
+ // set some values
+ writeListViewVector(writer2, new int[] {1, 2});
+ writeListViewVector(writer2, new int[] {3, 4});
+ writer2.setValueCount(3);
+
+ VectorEqualsVisitor visitor = new VectorEqualsVisitor();
+
+ assertFalse(visitor.vectorEquals(vector1, vector2));
+ }
+ }
+
@Test
public void testListVectorEquals() {
try (final ListVector vector1 = ListVector.empty("list", allocator);
@@ -2914,6 +2942,38 @@ public class TestValueVector {
}
}
+ @Test
+ public void testListViewVectorEquals() {
+ try (final ListViewVector vector1 = ListViewVector.empty("listview",
allocator);
+ final ListViewVector vector2 = ListViewVector.empty("listview",
allocator); ) {
+
+ UnionListViewWriter writer1 = vector1.getWriter();
+ writer1.allocate();
+
+ // set some values
+ writeListViewVector(writer1, new int[] {1, 2});
+ writeListViewVector(writer1, new int[] {3, 4});
+ writeListViewVector(writer1, new int[] {5, 6});
+ writer1.setValueCount(3);
+
+ UnionListViewWriter writer2 = vector2.getWriter();
+ writer2.allocate();
+
+ // set some values
+ writeListViewVector(writer2, new int[] {1, 2});
+ writeListViewVector(writer2, new int[] {3, 4});
+ writer2.setValueCount(2);
+
+ VectorEqualsVisitor visitor = new VectorEqualsVisitor();
+ assertFalse(visitor.vectorEquals(vector1, vector2));
+
+ writeListViewVector(writer2, new int[] {5, 6});
+ writer2.setValueCount(3);
+
+ assertTrue(visitor.vectorEquals(vector1, vector2));
+ }
+ }
+
@Test
public void testListVectorSetNull() {
try (final ListVector vector = ListVector.empty("list", allocator)) {
diff --git
a/java/vector/src/test/java/org/apache/arrow/vector/compare/TestRangeEqualsVisitor.java
b/java/vector/src/test/java/org/apache/arrow/vector/compare/TestRangeEqualsVisitor.java
index bab8c737f6..7e91b76043 100644
---
a/java/vector/src/test/java/org/apache/arrow/vector/compare/TestRangeEqualsVisitor.java
+++
b/java/vector/src/test/java/org/apache/arrow/vector/compare/TestRangeEqualsVisitor.java
@@ -37,10 +37,12 @@ import
org.apache.arrow.vector.compare.util.ValueEpsilonEqualizers;
import org.apache.arrow.vector.complex.DenseUnionVector;
import org.apache.arrow.vector.complex.FixedSizeListVector;
import org.apache.arrow.vector.complex.ListVector;
+import org.apache.arrow.vector.complex.ListViewVector;
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.UnionFixedSizeListWriter;
+import org.apache.arrow.vector.complex.impl.UnionListViewWriter;
import org.apache.arrow.vector.complex.impl.UnionListWriter;
import org.apache.arrow.vector.holders.NullableBigIntHolder;
import org.apache.arrow.vector.holders.NullableFloat4Holder;
@@ -201,6 +203,24 @@ public class TestRangeEqualsVisitor {
}
}
+ @Test
+ public void testListViewVectorWithDifferentChild() {
+ try (final ListViewVector vector1 = ListViewVector.empty("listview",
allocator);
+ final ListViewVector vector2 = ListViewVector.empty("listview",
allocator); ) {
+
+ vector1.allocateNew();
+ vector1.initializeChildrenFromFields(
+ Arrays.asList(Field.nullable("child", new ArrowType.Int(32, true))));
+
+ vector2.allocateNew();
+ vector2.initializeChildrenFromFields(
+ Arrays.asList(Field.nullable("child", new ArrowType.Int(64, true))));
+
+ RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector1, vector2);
+ assertFalse(visitor.rangeEquals(new Range(0, 0, 0)));
+ }
+ }
+
@Test
public void testListVectorRangeEquals() {
try (final ListVector vector1 = ListVector.empty("list", allocator);
@@ -233,6 +253,38 @@ public class TestRangeEqualsVisitor {
}
}
+ @Test
+ public void testListViewVectorRangeEquals() {
+ try (final ListViewVector vector1 = ListViewVector.empty("listview",
allocator);
+ final ListViewVector vector2 = ListViewVector.empty("listview",
allocator); ) {
+
+ UnionListViewWriter writer1 = vector1.getWriter();
+ writer1.allocate();
+
+ // set some values
+ writeListViewVector(writer1, new int[] {1, 2});
+ writeListViewVector(writer1, new int[] {3, 4});
+ writeListViewVector(writer1, new int[] {5, 6});
+ writeListViewVector(writer1, new int[] {7, 8});
+ writeListViewVector(writer1, new int[] {9, 10});
+ writer1.setValueCount(5);
+
+ UnionListViewWriter writer2 = vector2.getWriter();
+ writer2.allocate();
+
+ // set some values
+ writeListViewVector(writer2, new int[] {0, 0});
+ writeListViewVector(writer2, new int[] {3, 4});
+ writeListViewVector(writer2, new int[] {5, 6});
+ writeListViewVector(writer2, new int[] {7, 8});
+ writeListViewVector(writer2, new int[] {0, 0});
+ writer2.setValueCount(5);
+
+ RangeEqualsVisitor visitor = new RangeEqualsVisitor(vector1, vector2);
+ assertTrue(visitor.rangeEquals(new Range(1, 1, 3)));
+ }
+ }
+
@Test
public void testBitVectorRangeEquals() {
try (final BitVector vector1 = new BitVector("v1", allocator);
@@ -819,6 +871,38 @@ public class TestRangeEqualsVisitor {
}
}
+ @Test
+ public void testListViewVectorApproxEquals() {
+ try (final ListViewVector right = ListViewVector.empty("listview",
allocator);
+ final ListViewVector left1 = ListViewVector.empty("listview",
allocator);
+ final ListViewVector left2 = ListViewVector.empty("listview",
allocator); ) {
+
+ final float epsilon = 1.0E-6f;
+
+ UnionListViewWriter rightWriter = right.getWriter();
+ rightWriter.allocate();
+ writeListViewVector(rightWriter, new double[] {1, 2});
+ writeListViewVector(rightWriter, new double[] {1.01, 2.02});
+ rightWriter.setValueCount(2);
+
+ UnionListViewWriter leftWriter1 = left1.getWriter();
+ leftWriter1.allocate();
+ writeListViewVector(leftWriter1, new double[] {1, 2});
+ writeListViewVector(leftWriter1, new double[] {1.01 + epsilon / 2, 2.02
- epsilon / 2});
+ leftWriter1.setValueCount(2);
+
+ UnionListViewWriter leftWriter2 = left2.getWriter();
+ leftWriter2.allocate();
+ writeListViewVector(leftWriter2, new double[] {1, 2});
+ writeListViewVector(leftWriter2, new double[] {1.01 + epsilon * 2, 2.02
- epsilon * 2});
+ leftWriter2.setValueCount(2);
+
+ Range range = new Range(0, 0, right.getValueCount());
+ assertTrue(new ApproxEqualsVisitor(left1, right, epsilon,
epsilon).rangeEquals(range));
+ assertFalse(new ApproxEqualsVisitor(left2, right, epsilon,
epsilon).rangeEquals(range));
+ }
+ }
+
private void writeStructVector(NullableStructWriter writer, int value1, long
value2) {
writer.start();
writer.integer("f0").writeInt(value1);
@@ -841,6 +925,14 @@ public class TestRangeEqualsVisitor {
writer.endList();
}
+ private void writeListViewVector(UnionListViewWriter writer, int[] values) {
+ writer.startListView();
+ for (int v : values) {
+ writer.integer().writeInt(v);
+ }
+ writer.endListView();
+ }
+
private void writeFixedSizeListVector(UnionFixedSizeListWriter writer, int[]
values) {
writer.startList();
for (int v : values) {
@@ -856,4 +948,12 @@ public class TestRangeEqualsVisitor {
}
writer.endList();
}
+
+ private void writeListViewVector(UnionListViewWriter writer, double[]
values) {
+ writer.startListView();
+ for (double v : values) {
+ writer.float8().writeFloat8(v);
+ }
+ writer.endListView();
+ }
}
diff --git
a/java/vector/src/test/java/org/apache/arrow/vector/compare/TestTypeEqualsVisitor.java
b/java/vector/src/test/java/org/apache/arrow/vector/compare/TestTypeEqualsVisitor.java
index 4cd3603e20..d65096205f 100644
---
a/java/vector/src/test/java/org/apache/arrow/vector/compare/TestTypeEqualsVisitor.java
+++
b/java/vector/src/test/java/org/apache/arrow/vector/compare/TestTypeEqualsVisitor.java
@@ -33,6 +33,7 @@ import org.apache.arrow.vector.ViewVarBinaryVector;
import org.apache.arrow.vector.ViewVarCharVector;
import org.apache.arrow.vector.complex.DenseUnionVector;
import org.apache.arrow.vector.complex.ListVector;
+import org.apache.arrow.vector.complex.ListViewVector;
import org.apache.arrow.vector.complex.StructVector;
import org.apache.arrow.vector.complex.UnionVector;
import org.apache.arrow.vector.types.Types;
@@ -104,6 +105,22 @@ public class TestTypeEqualsVisitor {
}
}
+ @Test
+ public void testListViewTypeEquals() {
+ try (final ListViewVector right = ListViewVector.empty("listview",
allocator);
+ final ListViewVector left1 = ListViewVector.empty("listview",
allocator);
+ final ListViewVector left2 = ListViewVector.empty("listview",
allocator)) {
+
+ right.addOrGetVector(FieldType.nullable(new ArrowType.Utf8()));
+ left1.addOrGetVector(FieldType.nullable(new ArrowType.Utf8()));
+ left2.addOrGetVector(FieldType.nullable(new
ArrowType.FixedSizeBinary(2)));
+
+ TypeEqualsVisitor visitor = new TypeEqualsVisitor(right);
+ assertTrue(visitor.equals(left1));
+ assertFalse(visitor.equals(left2));
+ }
+ }
+
@Test
public void testStructTypeEquals() {
try (final StructVector right = StructVector.empty("struct", allocator);