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 3db62050da GH-37701: [Java] Add default comparators for more types
(#37748)
3db62050da is described below
commit 3db62050daa67b927810574dea60fd5b84bcb523
Author: James Duong <[email protected]>
AuthorDate: Fri Sep 15 14:45:08 2023 -0700
GH-37701: [Java] Add default comparators for more types (#37748)
### Rationale for this change
Add default comparators for more vector types to make algorithms easier to
use and provide more consistency for Java compared to other languages.
### What changes are included in this PR?
Add default type comparators for:
- BitVector
- DateDayVector
- DateMilliVector
- Decimal256Vector
- DecimalVector
- DurationVector
- IntervalDayVector
- TimeMicroVector
- TimeMilliVector
- TimeNanoVector
- TimeSecVector
- TimeStampVector
IntervalMonthDayNanoVector is not supported due to its public type
PeriodDuration not being Comparable.
BitVector's getWidth() method does not return valid data by design since
its length is smaller than 1 byte. Using a BitVector with a fixed-width type's
algorithm will throw an IllegalArgumentException.
### Are these changes tested?
Yes.
### Are there any user-facing changes?
No.
* Closes: #37701
Authored-by: James Duong <[email protected]>
Signed-off-by: David Li <[email protected]>
---
.../algorithm/sort/DefaultVectorComparators.java | 329 +++++++++++++++
.../sort/FixedWidthOutOfPlaceVectorSorter.java | 4 +
.../sort/TestDefaultVectorComparator.java | 447 +++++++++++++++++++++
.../org/apache/arrow/vector/Decimal256Vector.java | 12 +-
.../org/apache/arrow/vector/DecimalVector.java | 12 +-
.../org/apache/arrow/vector/DurationVector.java | 14 +-
.../org/apache/arrow/vector/IntervalDayVector.java | 18 +-
.../vector/testing/ValueVectorDataPopulator.java | 30 ++
8 files changed, 858 insertions(+), 8 deletions(-)
diff --git
a/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java
b/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java
index c418219170..99d66f9426 100644
---
a/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java
+++
b/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java
@@ -19,15 +19,31 @@ package org.apache.arrow.algorithm.sort;
import static
org.apache.arrow.vector.complex.BaseRepeatedValueVector.OFFSET_WIDTH;
+import java.math.BigDecimal;
+import java.time.Duration;
+
import org.apache.arrow.memory.util.ArrowBufPointer;
import org.apache.arrow.memory.util.ByteFunctionHelpers;
import org.apache.arrow.vector.BaseFixedWidthVector;
import org.apache.arrow.vector.BaseVariableWidthVector;
import org.apache.arrow.vector.BigIntVector;
+import org.apache.arrow.vector.BitVector;
+import org.apache.arrow.vector.DateDayVector;
+import org.apache.arrow.vector.DateMilliVector;
+import org.apache.arrow.vector.Decimal256Vector;
+import org.apache.arrow.vector.DecimalVector;
+import org.apache.arrow.vector.DurationVector;
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.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.TimeStampVector;
import org.apache.arrow.vector.TinyIntVector;
import org.apache.arrow.vector.UInt1Vector;
import org.apache.arrow.vector.UInt2Vector;
@@ -69,6 +85,32 @@ public class DefaultVectorComparators {
return (VectorValueComparator<T>) new UInt4Comparator();
} else if (vector instanceof UInt8Vector) {
return (VectorValueComparator<T>) new UInt8Comparator();
+ } else if (vector instanceof BitVector) {
+ return (VectorValueComparator<T>) new BitComparator();
+ } else if (vector instanceof DateDayVector) {
+ return (VectorValueComparator<T>) new DateDayComparator();
+ } else if (vector instanceof DateMilliVector) {
+ return (VectorValueComparator<T>) new DateMilliComparator();
+ } else if (vector instanceof Decimal256Vector) {
+ return (VectorValueComparator<T>) new Decimal256Comparator();
+ } else if (vector instanceof DecimalVector) {
+ return (VectorValueComparator<T>) new DecimalComparator();
+ } else if (vector instanceof DurationVector) {
+ return (VectorValueComparator<T>) new DurationComparator();
+ } else if (vector instanceof IntervalDayVector) {
+ return (VectorValueComparator<T>) new IntervalDayComparator();
+ } else if (vector instanceof IntervalMonthDayNanoVector) {
+ throw new IllegalArgumentException("No default comparator for " +
vector.getClass().getCanonicalName());
+ } else if (vector instanceof TimeMicroVector) {
+ return (VectorValueComparator<T>) new TimeMicroComparator();
+ } else if (vector instanceof TimeMilliVector) {
+ return (VectorValueComparator<T>) new TimeMilliComparator();
+ } else if (vector instanceof TimeNanoVector) {
+ return (VectorValueComparator<T>) new TimeNanoComparator();
+ } else if (vector instanceof TimeSecVector) {
+ return (VectorValueComparator<T>) new TimeSecComparator();
+ } else if (vector instanceof TimeStampVector) {
+ return (VectorValueComparator<T>) new TimeStampComparator();
}
} else if (vector instanceof BaseVariableWidthVector) {
return (VectorValueComparator<T>) new VariableWidthComparator();
@@ -345,6 +387,293 @@ public class DefaultVectorComparators {
}
}
+ /**
+ * Default comparator for bit type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class BitComparator extends VectorValueComparator<BitVector> {
+
+ public BitComparator() {
+ super(-1);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ boolean value1 = vector1.get(index1) != 0;
+ boolean value2 = vector2.get(index2) != 0;
+
+ return Boolean.compare(value1, value2);
+ }
+
+ @Override
+ public VectorValueComparator<BitVector> createNew() {
+ return new BitComparator();
+ }
+ }
+
+ /**
+ * Default comparator for DateDay type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class DateDayComparator extends
VectorValueComparator<DateDayVector> {
+
+ public DateDayComparator() {
+ super(DateDayVector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ int value1 = vector1.get(index1);
+ int value2 = vector2.get(index2);
+ return Integer.compare(value1, value2);
+ }
+
+ @Override
+ public VectorValueComparator<DateDayVector> createNew() {
+ return new DateDayComparator();
+ }
+ }
+
+ /**
+ * Default comparator for DateMilli type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class DateMilliComparator extends
VectorValueComparator<DateMilliVector> {
+
+ public DateMilliComparator() {
+ super(DateMilliVector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ long value1 = vector1.get(index1);
+ long value2 = vector2.get(index2);
+
+ return Long.compare(value1, value2);
+ }
+
+ @Override
+ public VectorValueComparator<DateMilliVector> createNew() {
+ return new DateMilliComparator();
+ }
+ }
+
+ /**
+ * Default comparator for Decimal256 type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class Decimal256Comparator extends
VectorValueComparator<Decimal256Vector> {
+
+ public Decimal256Comparator() {
+ super(Decimal256Vector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ BigDecimal value1 = vector1.getObjectNotNull(index1);
+ BigDecimal value2 = vector2.getObjectNotNull(index2);
+
+ return value1.compareTo(value2);
+ }
+
+ @Override
+ public VectorValueComparator<Decimal256Vector> createNew() {
+ return new Decimal256Comparator();
+ }
+ }
+
+ /**
+ * Default comparator for Decimal type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class DecimalComparator extends
VectorValueComparator<DecimalVector> {
+
+ public DecimalComparator() {
+ super(DecimalVector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ BigDecimal value1 = vector1.getObjectNotNull(index1);
+ BigDecimal value2 = vector2.getObjectNotNull(index2);
+
+ return value1.compareTo(value2);
+ }
+
+ @Override
+ public VectorValueComparator<DecimalVector> createNew() {
+ return new DecimalComparator();
+ }
+ }
+
+ /**
+ * Default comparator for Duration type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class DurationComparator extends
VectorValueComparator<DurationVector> {
+
+ public DurationComparator() {
+ super(DurationVector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ Duration value1 = vector1.getObjectNotNull(index1);
+ Duration value2 = vector2.getObjectNotNull(index2);
+
+ return value1.compareTo(value2);
+ }
+
+ @Override
+ public VectorValueComparator<DurationVector> createNew() {
+ return new DurationComparator();
+ }
+ }
+
+ /**
+ * Default comparator for IntervalDay type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class IntervalDayComparator extends
VectorValueComparator<IntervalDayVector> {
+
+ public IntervalDayComparator() {
+ super(IntervalDayVector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ Duration value1 = vector1.getObjectNotNull(index1);
+ Duration value2 = vector2.getObjectNotNull(index2);
+
+ return value1.compareTo(value2);
+ }
+
+ @Override
+ public VectorValueComparator<IntervalDayVector> createNew() {
+ return new IntervalDayComparator();
+ }
+ }
+
+ /**
+ * Default comparator for TimeMicro type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class TimeMicroComparator extends
VectorValueComparator<TimeMicroVector> {
+
+ public TimeMicroComparator() {
+ super(TimeMicroVector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ long value1 = vector1.get(index1);
+ long value2 = vector2.get(index2);
+
+ return Long.compare(value1, value2);
+ }
+
+ @Override
+ public VectorValueComparator<TimeMicroVector> createNew() {
+ return new TimeMicroComparator();
+ }
+ }
+
+ /**
+ * Default comparator for TimeMilli type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class TimeMilliComparator extends
VectorValueComparator<TimeMilliVector> {
+
+ public TimeMilliComparator() {
+ super(TimeMilliVector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ int value1 = vector1.get(index1);
+ int value2 = vector2.get(index2);
+
+ return Integer.compare(value1, value2);
+ }
+
+ @Override
+ public VectorValueComparator<TimeMilliVector> createNew() {
+ return new TimeMilliComparator();
+ }
+ }
+
+ /**
+ * Default comparator for TimeNano type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class TimeNanoComparator extends
VectorValueComparator<TimeNanoVector> {
+
+ public TimeNanoComparator() {
+ super(TimeNanoVector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ long value1 = vector1.get(index1);
+ long value2 = vector2.get(index2);
+
+ return Long.compare(value1, value2);
+ }
+
+ @Override
+ public VectorValueComparator<TimeNanoVector> createNew() {
+ return new TimeNanoComparator();
+ }
+ }
+
+ /**
+ * Default comparator for TimeSec type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class TimeSecComparator extends
VectorValueComparator<TimeSecVector> {
+
+ public TimeSecComparator() {
+ super(TimeSecVector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ int value1 = vector1.get(index1);
+ int value2 = vector2.get(index2);
+
+ return Integer.compare(value1, value2);
+ }
+
+ @Override
+ public VectorValueComparator<TimeSecVector> createNew() {
+ return new TimeSecComparator();
+ }
+ }
+
+ /**
+ * Default comparator for TimeSec type.
+ * The comparison is based on values, with null comes first.
+ */
+ public static class TimeStampComparator extends
VectorValueComparator<TimeStampVector> {
+
+ public TimeStampComparator() {
+ super(TimeStampVector.TYPE_WIDTH);
+ }
+
+ @Override
+ public int compareNotNull(int index1, int index2) {
+ long value1 = vector1.get(index1);
+ long value2 = vector2.get(index2);
+
+ return Long.compare(value1, value2);
+ }
+
+ @Override
+ public VectorValueComparator<TimeStampVector> createNew() {
+ return new TimeStampComparator();
+ }
+ }
+
/**
* Default comparator for {@link
org.apache.arrow.vector.BaseVariableWidthVector}.
* The comparison is in lexicographic order, with null comes first.
diff --git
a/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/FixedWidthOutOfPlaceVectorSorter.java
b/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/FixedWidthOutOfPlaceVectorSorter.java
index 43d604060d..c3b68facfd 100644
---
a/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/FixedWidthOutOfPlaceVectorSorter.java
+++
b/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/FixedWidthOutOfPlaceVectorSorter.java
@@ -21,6 +21,7 @@ import org.apache.arrow.memory.ArrowBuf;
import org.apache.arrow.memory.util.MemoryUtil;
import org.apache.arrow.util.Preconditions;
import org.apache.arrow.vector.BaseFixedWidthVector;
+import org.apache.arrow.vector.BitVector;
import org.apache.arrow.vector.BitVectorHelper;
import org.apache.arrow.vector.IntVector;
@@ -35,6 +36,9 @@ public class FixedWidthOutOfPlaceVectorSorter<V extends
BaseFixedWidthVector> im
@Override
public void sortOutOfPlace(V srcVector, V dstVector,
VectorValueComparator<V> comparator) {
+ if (srcVector instanceof BitVector) {
+ throw new IllegalArgumentException("BitVector is not supported with
FixedWidthOutOfPlaceVectorSorter.");
+ }
comparator.attachVector(srcVector);
int valueWidth = comparator.getValueWidth();
diff --git
a/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java
b/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java
index 818bb60d11..6205119774 100644
---
a/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java
+++
b/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java
@@ -25,8 +25,23 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.memory.RootAllocator;
import org.apache.arrow.vector.BigIntVector;
+import org.apache.arrow.vector.BitVector;
+import org.apache.arrow.vector.DateDayVector;
+import org.apache.arrow.vector.DateMilliVector;
+import org.apache.arrow.vector.Decimal256Vector;
+import org.apache.arrow.vector.DecimalVector;
+import org.apache.arrow.vector.DurationVector;
+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.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.TimeStampMilliVector;
+import org.apache.arrow.vector.TimeStampVector;
import org.apache.arrow.vector.TinyIntVector;
import org.apache.arrow.vector.UInt1Vector;
import org.apache.arrow.vector.UInt2Vector;
@@ -34,6 +49,7 @@ import org.apache.arrow.vector.UInt4Vector;
import org.apache.arrow.vector.UInt8Vector;
import org.apache.arrow.vector.complex.ListVector;
import org.apache.arrow.vector.testing.ValueVectorDataPopulator;
+import org.apache.arrow.vector.types.TimeUnit;
import org.apache.arrow.vector.types.Types;
import org.apache.arrow.vector.types.pojo.ArrowType;
import org.apache.arrow.vector.types.pojo.FieldType;
@@ -271,6 +287,76 @@ public class TestDefaultVectorComparator {
}
}
+ @Test
+ public void testCompareFloat4() {
+ try (Float4Vector vec = new Float4Vector("", allocator)) {
+ vec.allocateNew(9);
+ ValueVectorDataPopulator.setVector(
+ vec, -1.1f, 0.0f, 1.0f, null, 1.0f, 2.0f, Float.NaN, Float.NaN,
Float.POSITIVE_INFINITY,
+ Float.NEGATIVE_INFINITY);
+
+ VectorValueComparator<Float4Vector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+ assertTrue(comparator.compare(8, 3) > 0);
+
+ // NaN behavior.
+ assertTrue(comparator.compare(6, 7) == 0);
+ assertTrue(comparator.compare(7, 6) == 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ assertTrue(comparator.compare(6, 0) > 0);
+ assertTrue(comparator.compare(6, 8) > 0);
+ assertTrue(comparator.compare(6, 3) > 0);
+ }
+ }
+
+ @Test
+ public void testCompareFloat8() {
+ try (Float8Vector vec = new Float8Vector("", allocator)) {
+ vec.allocateNew(9);
+ ValueVectorDataPopulator.setVector(
+ vec, -1.1, 0.0, 1.0, null, 1.0, 2.0, Double.NaN, Double.NaN,
Double.POSITIVE_INFINITY,
+ Double.NEGATIVE_INFINITY);
+
+ VectorValueComparator<Float8Vector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+ assertTrue(comparator.compare(8, 3) > 0);
+
+ // NaN behavior.
+ assertTrue(comparator.compare(6, 7) == 0);
+ assertTrue(comparator.compare(7, 6) == 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ assertTrue(comparator.compare(6, 0) > 0);
+ assertTrue(comparator.compare(6, 8) > 0);
+ assertTrue(comparator.compare(6, 3) > 0);
+ }
+ }
+
@Test
public void testCompareLong() {
try (BigIntVector vec = new BigIntVector("", allocator)) {
@@ -393,6 +479,367 @@ public class TestDefaultVectorComparator {
}
}
+ @Test
+ public void testCompareBit() {
+ try (BitVector vec = new BitVector("", allocator)) {
+ vec.allocateNew(6);
+ ValueVectorDataPopulator.setVector(
+ vec, 1, 2, 0, 0, -1, null);
+
+ VectorValueComparator<BitVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) == 0);
+ assertTrue(comparator.compare(0, 2) > 0);
+ assertTrue(comparator.compare(0, 4) == 0);
+ assertTrue(comparator.compare(2, 1) < 0);
+ assertTrue(comparator.compare(2, 4) < 0);
+
+ // null first
+ assertTrue(comparator.compare(5, 0) < 0);
+ assertTrue(comparator.compare(5, 2) < 0);
+ }
+ }
+
+ @Test
+ public void testCompareDateDay() {
+ try (DateDayVector vec = new DateDayVector("", allocator)) {
+ vec.allocateNew(8);
+ ValueVectorDataPopulator.setVector(
+ vec, -1, 0, 1, null, 1, 5, Integer.MIN_VALUE + 1, Integer.MAX_VALUE);
+
+ VectorValueComparator<DateDayVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+
+ // potential overflow
+ assertTrue(comparator.compare(6, 7) < 0);
+ assertTrue(comparator.compare(7, 6) > 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ }
+ }
+
+ @Test
+ public void testCompareDateMilli() {
+ try (DateMilliVector vec = new DateMilliVector("", allocator)) {
+ vec.allocateNew(8);
+ ValueVectorDataPopulator.setVector(
+ vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+ VectorValueComparator<DateMilliVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+
+ // potential overflow
+ assertTrue(comparator.compare(6, 7) < 0);
+ assertTrue(comparator.compare(7, 6) > 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ }
+ }
+
+ @Test
+ public void testCompareDecimal() {
+ try (DecimalVector vec = new DecimalVector("", allocator, 10, 1)) {
+ vec.allocateNew(8);
+ ValueVectorDataPopulator.setVector(
+ vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+ VectorValueComparator<DecimalVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+
+ // potential overflow
+ assertTrue(comparator.compare(6, 7) < 0);
+ assertTrue(comparator.compare(7, 6) > 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ }
+ }
+
+ @Test
+ public void testCompareDecimal256() {
+ try (Decimal256Vector vec = new Decimal256Vector("", allocator, 10, 1)) {
+ vec.allocateNew(8);
+ ValueVectorDataPopulator.setVector(
+ vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+ VectorValueComparator<Decimal256Vector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+
+ // potential overflow
+ assertTrue(comparator.compare(6, 7) < 0);
+ assertTrue(comparator.compare(7, 6) > 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ }
+ }
+
+ @Test
+ public void testCompareDuration() {
+ try (DurationVector vec =
+ new DurationVector("", FieldType.nullable(new
ArrowType.Duration(TimeUnit.MILLISECOND)), allocator)) {
+ vec.allocateNew(8);
+ ValueVectorDataPopulator.setVector(
+ vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+ VectorValueComparator<DurationVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+
+ // potential overflow
+ assertTrue(comparator.compare(6, 7) < 0);
+ assertTrue(comparator.compare(7, 6) > 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ }
+ }
+
+ @Test
+ public void testCompareIntervalDay() {
+ try (IntervalDayVector vec =
+ new IntervalDayVector("", FieldType.nullable(new
ArrowType.Duration(TimeUnit.MILLISECOND)), allocator)) {
+ vec.allocateNew(8);
+ vec.set(0, -1, 0);
+ vec.set(1, 0, 0);
+ vec.set(2, 1, 0);
+ vec.setNull(3);
+ vec.set(4, -1, -1);
+ vec.set(5, 1, 1);
+ vec.set(6, 1, 1);
+ vec.set(7, -1, -1);
+
+ VectorValueComparator<IntervalDayVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+ assertTrue(comparator.compare(2, 5) < 0);
+ assertTrue(comparator.compare(0, 4) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 6) == 0);
+ assertTrue(comparator.compare(4, 7) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+ }
+ }
+
+ @Test
+ public void testCompareTimeMicro() {
+ try (TimeMicroVector vec =
+ new TimeMicroVector("", allocator)) {
+ vec.allocateNew(8);
+ ValueVectorDataPopulator.setVector(
+ vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+ VectorValueComparator<TimeMicroVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+
+ // potential overflow
+ assertTrue(comparator.compare(6, 7) < 0);
+ assertTrue(comparator.compare(7, 6) > 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ }
+ }
+
+ @Test
+ public void testCompareTimeMilli() {
+ try (TimeMilliVector vec = new TimeMilliVector("", allocator)) {
+ vec.allocateNew(8);
+ ValueVectorDataPopulator.setVector(
+ vec, -1, 0, 1, null, 1, 5, Integer.MIN_VALUE + 1, Integer.MAX_VALUE);
+
+ VectorValueComparator<TimeMilliVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+
+ // potential overflow
+ assertTrue(comparator.compare(6, 7) < 0);
+ assertTrue(comparator.compare(7, 6) > 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ }
+ }
+
+ @Test
+ public void testCompareTimeNano() {
+ try (TimeNanoVector vec =
+ new TimeNanoVector("", allocator)) {
+ vec.allocateNew(8);
+ ValueVectorDataPopulator.setVector(
+ vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+ VectorValueComparator<TimeNanoVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+
+ // potential overflow
+ assertTrue(comparator.compare(6, 7) < 0);
+ assertTrue(comparator.compare(7, 6) > 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ }
+ }
+
+ @Test
+ public void testCompareTimeSec() {
+ try (TimeSecVector vec = new TimeSecVector("", allocator)) {
+ vec.allocateNew(8);
+ ValueVectorDataPopulator.setVector(
+ vec, -1, 0, 1, null, 1, 5, Integer.MIN_VALUE + 1, Integer.MAX_VALUE);
+
+ VectorValueComparator<TimeSecVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+
+ // potential overflow
+ assertTrue(comparator.compare(6, 7) < 0);
+ assertTrue(comparator.compare(7, 6) > 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ }
+ }
+
+ @Test
+ public void testCompareTimeStamp() {
+ try (TimeStampMilliVector vec =
+ new TimeStampMilliVector("", allocator)) {
+ vec.allocateNew(8);
+ ValueVectorDataPopulator.setVector(
+ vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+ VectorValueComparator<TimeStampVector> comparator =
+ DefaultVectorComparators.createDefaultComparator(vec);
+ comparator.attachVector(vec);
+
+ assertTrue(comparator.compare(0, 1) < 0);
+ assertTrue(comparator.compare(0, 2) < 0);
+ assertTrue(comparator.compare(2, 1) > 0);
+
+ // test equality
+ assertTrue(comparator.compare(5, 5) == 0);
+ assertTrue(comparator.compare(2, 4) == 0);
+
+ // null first
+ assertTrue(comparator.compare(3, 4) < 0);
+ assertTrue(comparator.compare(5, 3) > 0);
+
+ // potential overflow
+ assertTrue(comparator.compare(6, 7) < 0);
+ assertTrue(comparator.compare(7, 6) > 0);
+ assertTrue(comparator.compare(7, 7) == 0);
+ }
+ }
+
@Test
public void testCheckNullsOnCompareIsFalseForNonNullableVector() {
try (IntVector vec = new IntVector("not nullable",
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java
b/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java
index 4ccee50d68..70a895ff40 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java
@@ -154,10 +154,20 @@ public final class Decimal256Vector extends
BaseFixedWidthVector {
if (isSet(index) == 0) {
return null;
} else {
- return DecimalUtility.getBigDecimalFromArrowBuf(valueBuffer, index,
scale, TYPE_WIDTH);
+ return getObjectNotNull(index);
}
}
+ /**
+ * Same as {@link #getObject(int)}, but does not check for null.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public BigDecimal getObjectNotNull(int index) {
+ return DecimalUtility.getBigDecimalFromArrowBuf(valueBuffer, index, scale,
TYPE_WIDTH);
+ }
+
/**
* Return precision for the decimal value.
*/
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java
index db04563df2..6a3ec60afc 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java
@@ -153,10 +153,20 @@ public final class DecimalVector extends
BaseFixedWidthVector {
if (isSet(index) == 0) {
return null;
} else {
- return DecimalUtility.getBigDecimalFromArrowBuf(valueBuffer, index,
scale, TYPE_WIDTH);
+ return getObjectNotNull(index);
}
}
+ /**
+ * Same as {@link #getObect(int)} but does not check for null.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public BigDecimal getObjectNotNull(int index) {
+ return DecimalUtility.getBigDecimalFromArrowBuf(valueBuffer, index, scale,
TYPE_WIDTH);
+ }
+
/**
* Return precision for the decimal value.
*/
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.java
index 1e1db0d1c3..b6abc16194 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.java
@@ -147,11 +147,21 @@ public final class DurationVector extends
BaseFixedWidthVector {
if (isSet(index) == 0) {
return null;
} else {
- final long value = get(valueBuffer, index);
- return toDuration(value, unit);
+ return getObjectNotNull(index);
}
}
+ /**
+ * Same as {@link #getObject(int)} but does not check for null.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Duration getObjectNotNull(int index) {
+ final long value = get(valueBuffer, index);
+ return toDuration(value, unit);
+ }
+
/**
* Converts the given value and unit to the appropriate {@link Duration}.
*/
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
index 35312ba7c9..7c0d19baa9 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
@@ -168,13 +168,23 @@ public final class IntervalDayVector extends
BaseFixedWidthVector {
if (isSet(index) == 0) {
return null;
} else {
- final long startIndex = (long) index * TYPE_WIDTH;
- final int days = valueBuffer.getInt(startIndex);
- final int milliseconds = valueBuffer.getInt(startIndex +
MILLISECOND_OFFSET);
- return Duration.ofDays(days).plusMillis(milliseconds);
+ return getObjectNotNull(index);
}
}
+ /**
+ * Same as {@link #getObject(int)} but does not check for null.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Duration getObjectNotNull(int index) {
+ final long startIndex = (long) index * TYPE_WIDTH;
+ final int days = valueBuffer.getInt(startIndex);
+ final int milliseconds = valueBuffer.getInt(startIndex +
MILLISECOND_OFFSET);
+ return Duration.ofDays(days).plusMillis(milliseconds);
+ }
+
/**
* Get the Interval value at a given index as a {@link StringBuilder} object.
*
diff --git
a/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java
b/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java
index 15d6a5cf99..f9f0357861 100644
---
a/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java
+++
b/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java
@@ -19,6 +19,7 @@ package org.apache.arrow.vector.testing;
import static org.junit.Assert.assertEquals;
+import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
@@ -29,6 +30,7 @@ import org.apache.arrow.vector.BitVector;
import org.apache.arrow.vector.BitVectorHelper;
import org.apache.arrow.vector.DateDayVector;
import org.apache.arrow.vector.DateMilliVector;
+import org.apache.arrow.vector.Decimal256Vector;
import org.apache.arrow.vector.DecimalVector;
import org.apache.arrow.vector.DurationVector;
import org.apache.arrow.vector.FixedSizeBinaryVector;
@@ -147,6 +149,34 @@ public class ValueVectorDataPopulator {
vector.setValueCount(length);
}
+ /**
+ * Populate values for Decimal256Vector.
+ */
+ public static void setVector(Decimal256Vector vector, Long... values) {
+ final int length = values.length;
+ vector.allocateNew(length);
+ for (int i = 0; i < length; i++) {
+ if (values[i] != null) {
+ vector.set(i, values[i]);
+ }
+ }
+ vector.setValueCount(length);
+ }
+
+ /**
+ * Populate values for Decimal256Vector.
+ */
+ public static void setVector(Decimal256Vector vector, BigDecimal... values) {
+ final int length = values.length;
+ vector.allocateNew(length);
+ for (int i = 0; i < length; i++) {
+ if (values[i] != null) {
+ vector.set(i, values[i]);
+ }
+ }
+ vector.setValueCount(length);
+ }
+
/**
* Populate values for DurationVector.
* @param values values of elapsed time in either seconds, milliseconds,
microseconds or nanoseconds.