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 c418219170380..99d66f94261ee 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 @@ 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 static VectorValueComparator createDefaultComp return (VectorValueComparator) new UInt4Comparator(); } else if (vector instanceof UInt8Vector) { return (VectorValueComparator) new UInt8Comparator(); + } else if (vector instanceof BitVector) { + return (VectorValueComparator) new BitComparator(); + } else if (vector instanceof DateDayVector) { + return (VectorValueComparator) new DateDayComparator(); + } else if (vector instanceof DateMilliVector) { + return (VectorValueComparator) new DateMilliComparator(); + } else if (vector instanceof Decimal256Vector) { + return (VectorValueComparator) new Decimal256Comparator(); + } else if (vector instanceof DecimalVector) { + return (VectorValueComparator) new DecimalComparator(); + } else if (vector instanceof DurationVector) { + return (VectorValueComparator) new DurationComparator(); + } else if (vector instanceof IntervalDayVector) { + return (VectorValueComparator) new IntervalDayComparator(); + } else if (vector instanceof IntervalMonthDayNanoVector) { + throw new IllegalArgumentException("No default comparator for " + vector.getClass().getCanonicalName()); + } else if (vector instanceof TimeMicroVector) { + return (VectorValueComparator) new TimeMicroComparator(); + } else if (vector instanceof TimeMilliVector) { + return (VectorValueComparator) new TimeMilliComparator(); + } else if (vector instanceof TimeNanoVector) { + return (VectorValueComparator) new TimeNanoComparator(); + } else if (vector instanceof TimeSecVector) { + return (VectorValueComparator) new TimeSecComparator(); + } else if (vector instanceof TimeStampVector) { + return (VectorValueComparator) new TimeStampComparator(); } } else if (vector instanceof BaseVariableWidthVector) { return (VectorValueComparator) new VariableWidthComparator(); @@ -345,6 +387,293 @@ public VectorValueComparator createNew() { } } + /** + * Default comparator for bit type. + * The comparison is based on values, with null comes first. + */ + public static class BitComparator extends VectorValueComparator { + + 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 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 { + + 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 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 { + + 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 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 { + + 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 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 { + + 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 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 { + + 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 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 { + + 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 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 { + + 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 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 { + + 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 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 { + + 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 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 { + + 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 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 { + + 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 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 43d604060d086..c3b68facfda97 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.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 im @Override public void sortOutOfPlace(V srcVector, V dstVector, VectorValueComparator 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 818bb60d116da..62051197740d8 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 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.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 void testCompareUInt8() { } } + @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 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 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 void testCompareByte() { } } + @Test + public void testCompareBit() { + try (BitVector vec = new BitVector("", allocator)) { + vec.allocateNew(6); + ValueVectorDataPopulator.setVector( + vec, 1, 2, 0, 0, -1, null); + + VectorValueComparator 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 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 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 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 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 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 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 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 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 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 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 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 4ccee50d6805a..70a895ff40496 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 BigDecimal getObject(int index) { 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 db04563df24d7..6a3ec60afc52e 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 BigDecimal getObject(int index) { 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 1e1db0d1c3c5f..b6abc16194b77 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 Duration getObject(int index) { 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 35312ba7c96a1..7c0d19baa9a6f 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 Duration getObject(int index) { 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 15d6a5cf993c4..f9f0357861c15 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 @@ 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.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 static void setVector(DecimalVector vector, Long... values) { 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.