Source:
<code>public void testMerging() { List<Type> types = ImmutableList.of(INTEGER, INTEGER, INTEGER); List<Integer> sortIndexes = ImmutableList.of(2); List<SortOrder> sortOrders = ImmutableList.of(SortOrder.ASC_NULLS_FIRST); List<List<Page>> pageLists = new ArrayList<>(); PageBuilder pageBuilder = new PageBuilder(types); for (int i = 0; i < 10; i++) { Iterator<Integer> values = IntStream.range(0, 1000) .mapToObj(ignored -> ThreadLocalRandom.current().nextInt(100_000)) <START> .sorted() <END> .iterator(); List<Page> pages = new ArrayList<>(); for (int j = 0; j < 10; j++) { for (int k = 0; k < 100; k++) { int n = values.next(); pageBuilder.declarePosition(); INTEGER.writeLong(pageBuilder.getBlockBuilder(0), n); INTEGER.writeLong(pageBuilder.getBlockBuilder(1), n * 22L); INTEGER.writeLong(pageBuilder.getBlockBuilder(2), n * 33L); } pages.add(pageBuilder.build()); pageBuilder.reset(); } pageLists.add(pages); assertFalse(values.hasNext()); } List<Iterator<Page>> pages = pageLists.stream() .map(List::iterator) .collect(toList()); Iterator<Page> iterator = new MergingPageIterator(pages, types, sortIndexes, sortOrders); List<Long> values = new ArrayList<>(); while (iterator.hasNext()) { Page page = iterator.next(); for (int i = 0; i < page.getPositionCount(); i++) { long x = INTEGER.getLong(page.getBlock(0), i); long y = INTEGER.getLong(page.getBlock(1), i); long z = INTEGER.getLong(page.getBlock(2), i); assertEquals(y, x * 22); assertEquals(z, x * 33); values.add(x); } } assertThat(values).isSorted(); }</code><technical_language>Consider adding some nulls</technical_language>

Target:
public void testMerging() { List<Type> types = ImmutableList.of(INTEGER, INTEGER); List<Integer> sortIndexes = ImmutableList.of(1); List<SortOrder> sortOrders = ImmutableList.of(SortOrder.ASC_NULLS_FIRST); List<List<Page>> pageLists = new ArrayList<>(); PageBuilder pageBuilder = new PageBuilder(types); for (int i = 0; i < 10; i++) { Iterator<Integer> values = IntStream.range(0, 1000) .map(ignored -> ThreadLocalRandom.current().nextInt(100_000)) .mapToObj(n -> ((n % 100) == 0) ? null : n) .sorted(nullsFirst(naturalOrder())) .iterator(); List<Page> pages = new ArrayList<>(); for (int j = 0; j < 10; j++) { for (int k = 0; k < 100; k++) { Integer n = values.next(); pageBuilder.declarePosition(); if (n == null) { pageBuilder.getBlockBuilder(0).appendNull(); pageBuilder.getBlockBuilder(1).appendNull(); } else { INTEGER.writeLong(pageBuilder.getBlockBuilder(0), n); INTEGER.writeLong(pageBuilder.getBlockBuilder(1), n * 22L); } } pages.add(pageBuilder.build()); pageBuilder.reset(); } pageLists.add(pages); assertFalse(values.hasNext()); } List<Iterator<Page>> pages = pageLists.stream() .map(List::iterator) .collect(toList()); Iterator<Page> iterator = new MergingPageIterator(pages, types, sortIndexes, sortOrders); List<Long> values = new ArrayList<>(); while (iterator.hasNext()) { Page page = iterator.next(); for (int i = 0; i < page.getPositionCount(); i++) { if (page.getBlock(0).isNull(i)) { assertTrue(page.getBlock(1).isNull(i)); values.add(null); } else { long x = INTEGER.getLong(page.getBlock(0), i); long y = INTEGER.getLong(page.getBlock(1), i); assertEquals(y, x * 22); values.add(x); } } } assertThat(values).isSortedAccordingTo(nullsFirst(naturalOrder())); }