diff --git a/src/main/java/com/facebook/presto/AggregationUtil.java b/src/main/java/com/facebook/presto/AggregationUtil.java index 823aa23d89e9d..5c69776888134 100644 --- a/src/main/java/com/facebook/presto/AggregationUtil.java +++ b/src/main/java/com/facebook/presto/AggregationUtil.java @@ -1,19 +1,19 @@ package com.facebook.presto; import com.google.common.base.Preconditions; -import com.google.common.collect.Range; + public class AggregationUtil { - public static void processGroup(SeekableIterator aggregationSource, AggregationFunction aggregation, Range positions) + public static void processGroup(SeekableIterator aggregationSource, AggregationFunction aggregation, Range positions) { RangePositionBlock positionBlock = new RangePositionBlock(positions); // goto start of range - aggregationSource.seekTo(positions.lowerEndpoint()); + aggregationSource.seekTo(positions.getStart()); Preconditions.checkState(aggregationSource.hasNext(), "Group start position not found in aggregation source"); // while we have data... - while (aggregationSource.hasNext() && aggregationSource.peek().getRange().isConnected(positions)) { + while (aggregationSource.hasNext() && aggregationSource.peek().getRange().overlaps(positions)) { // process aggregation aggregation.add(aggregationSource.next(), positionBlock); } diff --git a/src/main/java/com/facebook/presto/Block.java b/src/main/java/com/facebook/presto/Block.java index 4fac63e6e3261..dc9aae6b2fe17 100644 --- a/src/main/java/com/facebook/presto/Block.java +++ b/src/main/java/com/facebook/presto/Block.java @@ -1,6 +1,6 @@ package com.facebook.presto; -import com.google.common.collect.Range; + public interface Block { @@ -13,5 +13,5 @@ public interface Block Iterable getPositions(); - Range getRange(); + Range getRange(); } diff --git a/src/main/java/com/facebook/presto/BlockBuilder.java b/src/main/java/com/facebook/presto/BlockBuilder.java index 9d7b1bc0ffa19..4bbc1a6e155bc 100644 --- a/src/main/java/com/facebook/presto/BlockBuilder.java +++ b/src/main/java/com/facebook/presto/BlockBuilder.java @@ -1,7 +1,7 @@ package com.facebook.presto; import com.google.common.base.Preconditions; -import com.google.common.collect.Ranges; + import io.airlift.units.DataSize; import io.airlift.units.DataSize.Unit; @@ -87,6 +87,6 @@ public ValueBlock build() return EmptyValueBlock.INSTANCE; } - return new UncompressedValueBlock(Ranges.closed(startPosition, startPosition + count - 1), tupleInfo, sliceOutput.slice()); + return new UncompressedValueBlock(Range.create(startPosition, startPosition + count - 1), tupleInfo, sliceOutput.slice()); } } diff --git a/src/main/java/com/facebook/presto/DataScan3.java b/src/main/java/com/facebook/presto/DataScan3.java index 8d0663275df14..d670e4d21b2c6 100644 --- a/src/main/java/com/facebook/presto/DataScan3.java +++ b/src/main/java/com/facebook/presto/DataScan3.java @@ -23,7 +23,7 @@ public DataScan3(Iterator source, Iterator getPositions() } @Override - public Range getRange() + public Range getRange() { - return Ranges.open(0L, 0L); + throw new UnsupportedOperationException("Empty block doesn't have a range"); } @Override diff --git a/src/main/java/com/facebook/presto/EmptyValueBlock.java b/src/main/java/com/facebook/presto/EmptyValueBlock.java index add5507010a3b..d5427e840856d 100644 --- a/src/main/java/com/facebook/presto/EmptyValueBlock.java +++ b/src/main/java/com/facebook/presto/EmptyValueBlock.java @@ -4,8 +4,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; import com.google.common.collect.PeekingIterator; -import com.google.common.collect.Range; -import com.google.common.collect.Ranges; + + import java.util.Iterator; @@ -85,9 +85,9 @@ public Iterable getPositions() } @Override - public Range getRange() + public Range getRange() { - return Ranges.open(0L, 0L); + throw new UnsupportedOperationException("Empty block doesn't have a range"); } @Override diff --git a/src/main/java/com/facebook/presto/ForwardingSeekableIterator.java b/src/main/java/com/facebook/presto/ForwardingSeekableIterator.java index 18e2553c8a410..92a6676561c59 100644 --- a/src/main/java/com/facebook/presto/ForwardingSeekableIterator.java +++ b/src/main/java/com/facebook/presto/ForwardingSeekableIterator.java @@ -55,7 +55,7 @@ public boolean hasNext() public boolean seekTo(long position) { if (last != null) { - Preconditions.checkArgument(position >= last.getRange().lowerEndpoint(), "Cannot seek to position %s before current range [%s, %s]", position, last.getRange().lowerEndpoint(), last.getRange().upperEndpoint()); + Preconditions.checkArgument(position >= last.getRange().getStart(), "Cannot seek to position %s before current range [%s, %s]", position, last.getRange().getStart(), last.getRange().getEnd()); if (last.getRange().contains(position)) { seekedTo = last; return true; @@ -69,7 +69,7 @@ public boolean seekTo(long position) seekedTo = last; return true; } - else if (last.getRange().lowerEndpoint() > position) { + else if (last.getRange().getStart() > position) { seekedTo = last; return false; } diff --git a/src/main/java/com/facebook/presto/GroupBy.java b/src/main/java/com/facebook/presto/GroupBy.java index a10e31112da0c..9523db0decbbc 100644 --- a/src/main/java/com/facebook/presto/GroupBy.java +++ b/src/main/java/com/facebook/presto/GroupBy.java @@ -2,8 +2,8 @@ import com.google.common.collect.AbstractIterator; import com.google.common.collect.PeekingIterator; -import com.google.common.collect.Range; -import com.google.common.collect.Ranges; + + import java.util.Iterator; @@ -57,7 +57,7 @@ protected RunLengthEncodedBlock computeNext() } long endPosition = entry.getPosition(); - Range range = Ranges.closed(startPosition, endPosition); + Range range = Range.create(startPosition, endPosition); RunLengthEncodedBlock group = new RunLengthEncodedBlock(groupByKey, range); return group; diff --git a/src/main/java/com/facebook/presto/MaskedValueBlock.java b/src/main/java/com/facebook/presto/MaskedValueBlock.java index 3a898630a9e34..05573a5faccbe 100644 --- a/src/main/java/com/facebook/presto/MaskedValueBlock.java +++ b/src/main/java/com/facebook/presto/MaskedValueBlock.java @@ -6,7 +6,6 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterators; import com.google.common.collect.PeekingIterator; -import com.google.common.collect.Range; import java.util.Iterator; @@ -21,11 +20,12 @@ public static ValueBlock maskBlock(ValueBlock valueBlock, PositionBlock position return EmptyValueBlock.INSTANCE; } - Range intersection = valueBlock.getRange().intersection(positions.getRange()); - if (intersection.isEmpty()) { + if (!valueBlock.getRange().overlaps(positions.getRange())) { return EmptyValueBlock.INSTANCE; } + Range intersection = valueBlock.getRange().intersect(positions.getRange()); + if (valueBlock.isSingleValue() && positions.isPositionsContiguous()) { Tuple value = valueBlock.iterator().next(); return new RunLengthEncodedBlock(value, intersection); @@ -133,7 +133,7 @@ public Iterable getPositions() } @Override - public Range getRange() + public Range getRange() { return positionBlock.getRange(); } diff --git a/src/main/java/com/facebook/presto/PackedLongSerde.java b/src/main/java/com/facebook/presto/PackedLongSerde.java index d451cbdc36f7c..57fb33ef9d1e8 100644 --- a/src/main/java/com/facebook/presto/PackedLongSerde.java +++ b/src/main/java/com/facebook/presto/PackedLongSerde.java @@ -2,21 +2,21 @@ import com.google.common.base.Preconditions; import com.google.common.collect.AbstractIterator; -import com.google.common.collect.Range; -import com.google.common.collect.Ranges; + + import java.util.Iterator; public class PackedLongSerde { private final byte bitWidth; - private final Range allowedRange; + private final Range allowedRange; public PackedLongSerde(int bitWidth) { Preconditions.checkArgument(bitWidth > 0 && bitWidth <= Long.SIZE); this.bitWidth = (byte) bitWidth; - this.allowedRange = Ranges.closed(-1L << (bitWidth - 1), ~(-1L << (bitWidth - 1))); + this.allowedRange = Range.create(-1L << (bitWidth - 1), ~(-1L << (bitWidth - 1))); } public void serialize(Iterable items, SliceOutput sliceOutput) diff --git a/src/main/java/com/facebook/presto/Range.java b/src/main/java/com/facebook/presto/Range.java new file mode 100644 index 0000000000000..38c3035b33f25 --- /dev/null +++ b/src/main/java/com/facebook/presto/Range.java @@ -0,0 +1,115 @@ +package com.facebook.presto; + +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractIterator; + +import java.util.Iterator; + +public class Range + implements Iterable +{ + private final long start; + private final long end; + + public Range(long start, long end) + { + Preconditions.checkArgument(start <= end, "start (%s) must be <= end (%s)", start, end); + + this.start = start; + this.end = end; + } + + public static Range create(long start, long end) + { + return new Range(start, end); + } + + public long getStart() + { + return start; + } + + public long getEnd() + { + return end; + } + + public long length() + { + return end - start + 1; + } + + public boolean contains(long value) + { + return value >= start && value <= end; + } + + public boolean overlaps(Range other) + { + return start <= other.end && other.start <= end; + } + + public Range intersect(Range other) + { + Preconditions.checkArgument(overlaps(other), "Ranges do not overlap %s vs %s", this, other); + + return create(Math.max(start, other.start), Math.min(end, other.end)); + } + + public String toString() + { + return String.format("[%s..%s]", start, end); + } + + @Override + public boolean equals(Object o) + { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Range range = (Range) o; + + if (end != range.end) { + return false; + } + if (start != range.start) { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + int result = (int) (start ^ (start >>> 32)); + result = 31 * result + (int) (end ^ (end >>> 32)); + return result; + } + + @Override + public Iterator iterator() + { + return new AbstractIterator() + { + private long current = start; + + @Override + protected Long computeNext() + { + if (current > end) { + endOfData(); + return null; + } + + long result = current; + ++current; + return result; + } + }; + } +} diff --git a/src/main/java/com/facebook/presto/RangePositionBlock.java b/src/main/java/com/facebook/presto/RangePositionBlock.java index 849974951a8ce..c40ed13bbb3fc 100644 --- a/src/main/java/com/facebook/presto/RangePositionBlock.java +++ b/src/main/java/com/facebook/presto/RangePositionBlock.java @@ -1,18 +1,14 @@ package com.facebook.presto; import com.google.common.base.Function; -import com.google.common.collect.DiscreteDomains; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Range; - -import javax.annotation.Nullable; public class RangePositionBlock implements PositionBlock { - private final Range range; + private final Range range; - public RangePositionBlock(Range range) + public RangePositionBlock(Range range) { this.range = range; } @@ -24,11 +20,11 @@ public PositionBlock filter(PositionBlock positionBlock) { } if (positionBlock.isPositionsContiguous()) { - Range intersection = range.intersection(positionBlock.getRange()); - if (intersection.isEmpty()) { + if (!range.overlaps(positionBlock.getRange())) { return EmptyPositionBlock.INSTANCE; } - return new RangePositionBlock(intersection); + + return new RangePositionBlock(range.intersect(positionBlock.getRange())); } ImmutableList.Builder builder = ImmutableList.builder(); @@ -47,13 +43,13 @@ public PositionBlock filter(PositionBlock positionBlock) { @Override public boolean isEmpty() { - return range.isEmpty(); + return false; } @Override public int getCount() { - return (int) (range.upperEndpoint() - range.lowerEndpoint() + 1); + return (int) range.length(); } @Override @@ -77,33 +73,33 @@ public boolean isPositionsContiguous() @Override public Iterable getPositions() { - return range.asSet(DiscreteDomains.longs()); + return range; } @Override - public Range getRange() + public Range getRange() { return range; } @Override - public boolean apply(@Nullable Long input) + public boolean apply(Long input) { - return range.apply(input); + return range.contains(input); } @Override public String toString() { - return String.format("[%s..%s]", range.lowerEndpoint(), range.upperEndpoint()); + return String.format("[%s..%s]", range.getStart(), range.getEnd()); } - public static Function> rangeGetter() + public static Function rangeGetter() { - return new Function>() + return new Function() { @Override - public Range apply(RangePositionBlock input) + public Range apply(RangePositionBlock input) { return input.getRange(); } diff --git a/src/main/java/com/facebook/presto/RunLengthEncodedBlock.java b/src/main/java/com/facebook/presto/RunLengthEncodedBlock.java index defcfcad3e907..74a4b76015189 100644 --- a/src/main/java/com/facebook/presto/RunLengthEncodedBlock.java +++ b/src/main/java/com/facebook/presto/RunLengthEncodedBlock.java @@ -2,10 +2,8 @@ import com.google.common.base.Function; import com.google.common.base.Predicate; -import com.google.common.collect.DiscreteDomains; import com.google.common.collect.Iterators; import com.google.common.collect.PeekingIterator; -import com.google.common.collect.Range; import java.util.Collections; import java.util.Iterator; @@ -14,9 +12,9 @@ public class RunLengthEncodedBlock implements ValueBlock { private final Tuple value; - private final Range range; + private final Range range; - public RunLengthEncodedBlock(Tuple value, Range range) + public RunLengthEncodedBlock(Tuple value, Range range) { this.value = value; this.range = range; @@ -79,7 +77,7 @@ public boolean isEmpty() @Override public int getCount() { - return (int) (range.upperEndpoint() - range.lowerEndpoint() + 1); + return (int) (range.getEnd() - range.getStart() + 1); } @Override @@ -103,11 +101,11 @@ public boolean isPositionsContiguous() @Override public Iterable getPositions() { - return range.asSet(DiscreteDomains.longs()); + return range; } @Override - public Range getRange() + public Range getRange() { return range; } diff --git a/src/main/java/com/facebook/presto/UncompressedPositionBlock.java b/src/main/java/com/facebook/presto/UncompressedPositionBlock.java index 8b9860a90b696..8d423c04aa750 100644 --- a/src/main/java/com/facebook/presto/UncompressedPositionBlock.java +++ b/src/main/java/com/facebook/presto/UncompressedPositionBlock.java @@ -2,8 +2,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; -import com.google.common.collect.Range; -import com.google.common.collect.Ranges; + + import java.util.List; @@ -16,7 +16,7 @@ public class UncompressedPositionBlock implements PositionBlock { private final List positions; - private final Range range; + private final Range range; public UncompressedPositionBlock(long... positions) { @@ -30,7 +30,7 @@ public UncompressedPositionBlock(List positions) this.positions = ImmutableList.copyOf(positions); - this.range = Ranges.closed(positions.get(0), positions.get(positions.size() - 1)); + this.range = Range.create(positions.get(0), positions.get(positions.size() - 1)); } public PositionBlock filter(PositionBlock positionBlock) { @@ -88,7 +88,7 @@ public Iterable getPositions() } @Override - public Range getRange() + public Range getRange() { return range; } diff --git a/src/main/java/com/facebook/presto/UncompressedValueBlock.java b/src/main/java/com/facebook/presto/UncompressedValueBlock.java index fa300c73b1e31..33b3f6c17e619 100644 --- a/src/main/java/com/facebook/presto/UncompressedValueBlock.java +++ b/src/main/java/com/facebook/presto/UncompressedValueBlock.java @@ -3,24 +3,22 @@ import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.collect.AbstractIterator; -import com.google.common.collect.DiscreteDomains; import com.google.common.collect.Iterators; import com.google.common.collect.PeekingIterator; -import com.google.common.collect.Range; import java.util.Iterator; public class UncompressedValueBlock implements ValueBlock { - private final Range range; + private final Range range; private final TupleInfo tupleInfo; private final Slice slice; - public UncompressedValueBlock(Range range, TupleInfo tupleInfo, Slice slice) + public UncompressedValueBlock(Range range, TupleInfo tupleInfo, Slice slice) { Preconditions.checkNotNull(range, "range is null"); - Preconditions.checkArgument(range.lowerEndpoint() >= 0, "range start position is negative"); + Preconditions.checkArgument(range.getStart() >= 0, "range start position is negative"); Preconditions.checkNotNull(tupleInfo, "tupleInfo is null"); Preconditions.checkNotNull(slice, "data is null"); @@ -107,7 +105,7 @@ protected Pair computeNext() Slice row = currentPositionToEnd.slice(0, size); - long position = index + range.lowerEndpoint(); + long position = index + range.getStart(); index++; return new Pair(position, new Tuple(row, tupleInfo)); } @@ -123,7 +121,7 @@ public boolean isEmpty() @Override public int getCount() { - return (int) (range.upperEndpoint() - range.lowerEndpoint() + 1); + return (int) (range.getEnd() - range.getStart() + 1); } @Override @@ -147,11 +145,11 @@ public boolean isPositionsContiguous() @Override public Iterable getPositions() { - return range.asSet(DiscreteDomains.longs()); + return range; } @Override - public Range getRange() + public Range getRange() { return range; } diff --git a/src/test/java/com/facebook/presto/TestExample.java b/src/test/java/com/facebook/presto/TestExample.java index 0d4ecfe003d71..dcad092e6564d 100644 --- a/src/test/java/com/facebook/presto/TestExample.java +++ b/src/test/java/com/facebook/presto/TestExample.java @@ -1,7 +1,7 @@ package com.facebook.presto; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Ranges; + import java.util.Iterator; @@ -29,9 +29,9 @@ public static void main(String[] args) private static DataScan3 newScan() { Iterator values = ImmutableList.builder() - .add(new UncompressedValueBlock(Ranges.closed(0L, 5L), new TupleInfo(FIXED_INT_64), Slices.wrappedBuffer(new byte[]{'a', 'b', 'c', 'd', 'e', 'f'}))) - .add(new UncompressedValueBlock(Ranges.closed(20L, 25L), new TupleInfo(FIXED_INT_64), Slices.wrappedBuffer(new byte[]{'h', 'i', 'j', 'k', 'l', 'm'}))) - .add(new UncompressedValueBlock(Ranges.closed(30L, 35L), new TupleInfo(FIXED_INT_64), Slices.wrappedBuffer(new byte[]{'n', 'o', 'p', 'q', 'r', 's'}))) + .add(new UncompressedValueBlock(Range.create(0L, 5L), new TupleInfo(FIXED_INT_64), Slices.wrappedBuffer(new byte[]{'a', 'b', 'c', 'd', 'e', 'f'}))) + .add(new UncompressedValueBlock(Range.create(20L, 25L), new TupleInfo(FIXED_INT_64), Slices.wrappedBuffer(new byte[]{'h', 'i', 'j', 'k', 'l', 'm'}))) + .add(new UncompressedValueBlock(Range.create(30L, 35L), new TupleInfo(FIXED_INT_64), Slices.wrappedBuffer(new byte[]{'n', 'o', 'p', 'q', 'r', 's'}))) .build() .iterator(); diff --git a/src/test/java/com/facebook/presto/TestForwardingSeekableIterator.java b/src/test/java/com/facebook/presto/TestForwardingSeekableIterator.java index 396fb951d4b3b..8ab44a1bab6b0 100644 --- a/src/test/java/com/facebook/presto/TestForwardingSeekableIterator.java +++ b/src/test/java/com/facebook/presto/TestForwardingSeekableIterator.java @@ -2,8 +2,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; -import com.google.common.collect.Range; -import com.google.common.collect.Ranges; + + import org.testng.annotations.Test; import java.util.List; @@ -15,17 +15,17 @@ public class TestForwardingSeekableIterator { - private final static List> RANGES = ImmutableList.of( - Ranges.closed(0L, 9L), - Ranges.closed(10L, 19L), - Ranges.closed(20L, 29L), - Ranges.closed(40L, 49L), - Ranges.closed(50L, 59L)); + private final static List RANGES = ImmutableList.of( + Range.create(0L, 9L), + Range.create(10L, 19L), + Range.create(20L, 29L), + Range.create(40L, 49L), + Range.create(50L, 59L)); @Test public void testBasicIteration() { - ImmutableList> actual = ImmutableList.copyOf(Iterators.transform(newIterator(), rangeGetter())); + ImmutableList actual = ImmutableList.copyOf(Iterators.transform(newIterator(), rangeGetter())); assertEquals(actual, RANGES); } @@ -35,7 +35,7 @@ public void testPeek() { ForwardingSeekableIterator iterator = newIterator(); - assertEquals(iterator.peek().getRange(), Ranges.closed(0L, 9L)); + assertEquals(iterator.peek().getRange(), Range.create(0L, 9L)); } @Test @@ -45,7 +45,7 @@ public void testSeek() assertTrue(iterator.seekTo(25)); assertTrue(iterator.hasNext()); - assertEquals(iterator.peek().getRange(), Ranges.closed(20L, 29L)); + assertEquals(iterator.peek().getRange(), Range.create(20L, 29L)); } @Test @@ -69,7 +69,7 @@ public void testSeekBackwards() RangePositionBlock first = iterator.next(); iterator.next(); - iterator.seekTo(first.getRange().lowerEndpoint()); + iterator.seekTo(first.getRange().getStart()); } @Test @@ -79,8 +79,8 @@ public void testSeekToMissing() assertFalse(iterator.seekTo(35)); assertTrue(iterator.hasNext()); - assertEquals(iterator.peek().getRange(), Ranges.closed(40L, 49L)); - assertEquals(iterator.next().getRange(), Ranges.closed(40L, 49L)); + assertEquals(iterator.peek().getRange(), Range.create(40L, 49L)); + assertEquals(iterator.next().getRange(), Range.create(40L, 49L)); } @Test @@ -96,7 +96,7 @@ private ForwardingSeekableIterator newIterator() { ImmutableList.Builder builder = ImmutableList.builder(); - for (Range range : RANGES) { + for (Range range : RANGES) { builder.add(new RangePositionBlock(range)); } diff --git a/src/test/java/com/facebook/presto/TestMaskedValueBlock.java b/src/test/java/com/facebook/presto/TestMaskedValueBlock.java index eddf6da1f86e2..d8a7673699399 100644 --- a/src/test/java/com/facebook/presto/TestMaskedValueBlock.java +++ b/src/test/java/com/facebook/presto/TestMaskedValueBlock.java @@ -4,7 +4,6 @@ package com.facebook.presto; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Ranges; import org.testng.annotations.Test; import static com.facebook.presto.TupleInfo.Type.FIXED_INT_64; @@ -26,7 +25,7 @@ public void testMaskUncompressedBlock() assertFalse(tuples.isEmpty()); assertEquals(tuples.getCount(), 4); assertEquals(ImmutableList.copyOf(tuples.getPositions()), ImmutableList.of(10L, 12L, 14L, 16L)); - assertEquals(tuples.getRange(), Ranges.closed(10L, 16L)); + assertEquals(tuples.getRange(), Range.create(10L, 16L)); assertFalse(tuples.isPositionsContiguous()); assertFalse(tuples.isSingleValue()); @@ -49,13 +48,13 @@ public void testMaskUncompressedBlock() public void testMaskRunLengthEncodedBlock() throws Exception { - ValueBlock valueBlock = new RunLengthEncodedBlock(createTuple("run"), Ranges.closed(10L, 19L)); - ValueBlock tuples = MaskedValueBlock.maskBlock(valueBlock, new RangePositionBlock(Ranges.closed(12L, 15L))); + ValueBlock valueBlock = new RunLengthEncodedBlock(createTuple("run"), Range.create(10L, 19L)); + ValueBlock tuples = MaskedValueBlock.maskBlock(valueBlock, new RangePositionBlock(Range.create(12L, 15L))); assertFalse(tuples.isEmpty()); assertEquals(tuples.getCount(), 4); assertEquals(ImmutableList.copyOf(tuples.getPositions()), ImmutableList.of(12L, 13L, 14L, 15L)); - assertEquals(tuples.getRange(), Ranges.closed(12L, 15L)); + assertEquals(tuples.getRange(), Range.create(12L, 15L)); assertTrue(tuples.isPositionsContiguous()); assertTrue(tuples.isSingleValue()); diff --git a/src/test/java/com/facebook/presto/TestRange.java b/src/test/java/com/facebook/presto/TestRange.java new file mode 100644 index 0000000000000..8c4f1660eddbe --- /dev/null +++ b/src/test/java/com/facebook/presto/TestRange.java @@ -0,0 +1,78 @@ +package com.facebook.presto; + +import com.google.common.collect.ImmutableList; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +public class TestRange +{ + @Test + public void testBasic() + { + Range range = Range.create(10, 20); + assertEquals(range.getStart(), 10); + assertEquals(range.getEnd(), 20); + } + + @Test + public void testSize() + { + assertEquals(Range.create(0, 0).length(), 1); + assertEquals(Range.create(0, 9).length(), 10); + assertEquals(Range.create(-9, 0).length(), 10); + } + + @Test + public void testOverlaps() + { + assertTrue(Range.create(0, 0).overlaps(Range.create(0, 0))); + assertTrue(Range.create(0, 10).overlaps(Range.create(-10, 0))); + assertTrue(Range.create(0, 10).overlaps(Range.create(5, 20))); + assertTrue(Range.create(0, 10).overlaps(Range.create(0, 10))); + assertFalse(Range.create(0, 10).overlaps(Range.create(20, 30))); + assertFalse(Range.create(20, 30).overlaps(Range.create(0, 10))); + } + + @Test + public void testContainsValue() + { + assertTrue(Range.create(0, 0).contains(0)); + assertFalse(Range.create(0, 0).contains(-1)); + assertFalse(Range.create(0, 0).contains(1)); + + assertFalse(Range.create(0, 10).contains(-1)); + assertTrue(Range.create(0, 10).contains(0)); + assertTrue(Range.create(0, 10).contains(5)); + assertTrue(Range.create(0, 10).contains(10)); + assertFalse(Range.create(0, 10).contains(11)); + } + + @Test + public void testIntersect() + { + assertEquals(Range.create(0, 20).intersect(Range.create(5, 15)), Range.create(5, 15)); + assertEquals(Range.create(0, 20).intersect(Range.create(-10, 10)), Range.create(0, 10)); + assertEquals(Range.create(0, 20).intersect(Range.create(15, 30)), Range.create(15, 20)); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = ".*<=.*") + public void createInvalid() + { + Range.create(10, 0); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = ".*do not overlap.*") + public void testIntersectNonOverlapping() + { + Range.create(0, 10).intersect(Range.create(20, 30)); + } + + @Test + public void testIteration() + { + assertEquals(ImmutableList.copyOf(Range.create(0, 5)), ImmutableList.of(0L, 1L, 2L, 3L, 4L, 5L)); + } +}