Skip to content

Commit

Permalink
Remove null vector from ArrayBlock, MapBlock, and RowBlock when all v…
Browse files Browse the repository at this point in the history
…alues are not null

This reverts commit d7256c5.
  • Loading branch information
Ying Su authored and yingsu00 committed Sep 10, 2018
1 parent 988f0f2 commit df5131c
Show file tree
Hide file tree
Showing 24 changed files with 106 additions and 81 deletions.
Expand Up @@ -514,7 +514,7 @@ public Block apply(Block block)
valueIsNull[i] = arrayBlock.isNull(i); valueIsNull[i] = arrayBlock.isNull(i);
offsets[i + 1] = offsets[i] + arrayBlock.getLength(i); offsets[i + 1] = offsets[i] + arrayBlock.getLength(i);
} }
return ArrayBlock.fromElementBlock(arrayBlock.getPositionCount(), valueIsNull, offsets, elementsBlock); return ArrayBlock.fromElementBlock(arrayBlock.getPositionCount(), Optional.of(valueIsNull), offsets, elementsBlock);
} }
} }


Expand Down Expand Up @@ -550,7 +550,7 @@ public Block apply(Block block)
valueIsNull[i] = mapBlock.isNull(i); valueIsNull[i] = mapBlock.isNull(i);
offsets[i + 1] = offsets[i] + mapBlock.getEntryCount(i); offsets[i + 1] = offsets[i] + mapBlock.getEntryCount(i);
} }
return ((MapType) toType).createBlockFromKeyValue(valueIsNull, offsets, keysBlock, valuesBlock); return ((MapType) toType).createBlockFromKeyValue(Optional.of(valueIsNull), offsets, keysBlock, valuesBlock);
} }
} }


Expand Down Expand Up @@ -600,7 +600,7 @@ else if (i < rowBlock.getFieldCount()) {
for (int i = 0; i < rowBlock.getPositionCount(); i++) { for (int i = 0; i < rowBlock.getPositionCount(); i++) {
valueIsNull[i] = rowBlock.isNull(i); valueIsNull[i] = rowBlock.isNull(i);
} }
return RowBlock.fromFieldBlocks(valueIsNull, fields); return RowBlock.fromFieldBlocks(valueIsNull.length, Optional.of(valueIsNull), fields);
} }
} }


Expand Down
Expand Up @@ -144,7 +144,7 @@ private ColumnChunk readArray(GroupField field)
BooleanList valueIsNull = new BooleanArrayList(); BooleanList valueIsNull = new BooleanArrayList();


calculateCollectionOffsets(field, offsets, valueIsNull, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels()); calculateCollectionOffsets(field, offsets, valueIsNull, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels());
Block arrayBlock = ArrayBlock.fromElementBlock(valueIsNull.size(), valueIsNull.toBooleanArray(), offsets.toIntArray(), columnChunk.getBlock()); Block arrayBlock = ArrayBlock.fromElementBlock(valueIsNull.size(), Optional.of(valueIsNull.toBooleanArray()), offsets.toIntArray(), columnChunk.getBlock());
return new ColumnChunk(arrayBlock, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels()); return new ColumnChunk(arrayBlock, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels());
} }


Expand All @@ -161,7 +161,7 @@ private ColumnChunk readMap(GroupField field)
IntList offsets = new IntArrayList(); IntList offsets = new IntArrayList();
BooleanList valueIsNull = new BooleanArrayList(); BooleanList valueIsNull = new BooleanArrayList();
calculateCollectionOffsets(field, offsets, valueIsNull, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels()); calculateCollectionOffsets(field, offsets, valueIsNull, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels());
Block mapBlock = ((MapType) field.getType()).createBlockFromKeyValue(valueIsNull.toBooleanArray(), offsets.toIntArray(), blocks[0], blocks[1]); Block mapBlock = ((MapType) field.getType()).createBlockFromKeyValue(Optional.of(valueIsNull.toBooleanArray()), offsets.toIntArray(), blocks[0], blocks[1]);
return new ColumnChunk(mapBlock, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels()); return new ColumnChunk(mapBlock, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels());
} }


Expand All @@ -185,7 +185,8 @@ private ColumnChunk readStruct(GroupField field)
} }
} }
BooleanList structIsNull = ParquetStructColumnReader.calculateStructOffsets(field, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels()); BooleanList structIsNull = ParquetStructColumnReader.calculateStructOffsets(field, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels());
Block rowBlock = RowBlock.fromFieldBlocks(structIsNull.toBooleanArray(), blocks); boolean[] structIsNullVector = structIsNull.toBooleanArray();
Block rowBlock = RowBlock.fromFieldBlocks(structIsNullVector.length, Optional.of(structIsNullVector), blocks);
return new ColumnChunk(rowBlock, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels()); return new ColumnChunk(rowBlock, columnChunk.getDefinitionLevels(), columnChunk.getRepetitionLevels());
} }


Expand Down
Expand Up @@ -180,11 +180,11 @@ public void testCompactBlock()
int[] offsets = {0, 1, 1, 2, 4, 8, 16}; int[] offsets = {0, 1, 1, 2, 4, 8, 16};
boolean[] valueIsNull = {false, true, false, false, false, false}; boolean[] valueIsNull = {false, true, false, false, false, false};


testCompactBlock(fromElementBlock(0, new boolean[0], new int[1], emptyValueBlock)); testCompactBlock(fromElementBlock(0, Optional.empty(), new int[1], emptyValueBlock));
testCompactBlock(fromElementBlock(valueIsNull.length, valueIsNull, offsets, compactValueBlock)); testCompactBlock(fromElementBlock(valueIsNull.length, Optional.of(valueIsNull), offsets, compactValueBlock));
testIncompactBlock(fromElementBlock(valueIsNull.length - 1, valueIsNull, offsets, compactValueBlock)); testIncompactBlock(fromElementBlock(valueIsNull.length - 1, Optional.of(valueIsNull), offsets, compactValueBlock));
// underlying value block is not compact // underlying value block is not compact
testIncompactBlock(fromElementBlock(valueIsNull.length, valueIsNull, offsets, inCompactValueBlock)); testIncompactBlock(fromElementBlock(valueIsNull.length, Optional.of(valueIsNull), offsets, inCompactValueBlock));
} }


private static BlockBuilder createBlockBuilderWithValues(long[][][] expectedValues) private static BlockBuilder createBlockBuilderWithValues(long[][][] expectedValues)
Expand Down
Expand Up @@ -72,12 +72,12 @@ public void testCompactBlock()
int[] offsets = {0, 1, 1, 2, 4, 8, 16}; int[] offsets = {0, 1, 1, 2, 4, 8, 16};
boolean[] mapIsNull = {false, true, false, false, false, false}; boolean[] mapIsNull = {false, true, false, false, false, false};


testCompactBlock(mapType(TINYINT, TINYINT).createBlockFromKeyValue(new boolean[0], new int[1], emptyBlock, emptyBlock)); testCompactBlock(mapType(TINYINT, TINYINT).createBlockFromKeyValue(Optional.empty(), new int[1], emptyBlock, emptyBlock));
testCompactBlock(mapType(TINYINT, TINYINT).createBlockFromKeyValue(mapIsNull, offsets, compactKeyBlock, compactValueBlock)); testCompactBlock(mapType(TINYINT, TINYINT).createBlockFromKeyValue(Optional.of(mapIsNull), offsets, compactKeyBlock, compactValueBlock));
// TODO: Add test case for a sliced MapBlock // TODO: Add test case for a sliced MapBlock


// underlying key/value block is not compact // underlying key/value block is not compact
testIncompactBlock(mapType(TINYINT, TINYINT).createBlockFromKeyValue(mapIsNull, offsets, inCompactKeyBlock, inCompactValueBlock)); testIncompactBlock(mapType(TINYINT, TINYINT).createBlockFromKeyValue(Optional.of(mapIsNull), offsets, inCompactKeyBlock, inCompactValueBlock));
} }


private Map<String, Long>[] createTestMap(int... entryCounts) private Map<String, Long>[] createTestMap(int... entryCounts)
Expand Down Expand Up @@ -158,7 +158,7 @@ private Block createBlockWithValuesFromKeyValueBlock(Map<String, Long>[] maps)
offsets[i + 1] = offsets[i] + map.size(); offsets[i + 1] = offsets[i] + map.size();
} }
} }
return mapType(VARCHAR, BIGINT).createBlockFromKeyValue(mapIsNull, offsets, createStringsBlock(keys), createLongsBlock(values)); return mapType(VARCHAR, BIGINT).createBlockFromKeyValue(Optional.of(mapIsNull), offsets, createStringsBlock(keys), createLongsBlock(values));
} }


private void createBlockBuilderWithValues(Map<String, Long> map, BlockBuilder mapBlockBuilder) private void createBlockBuilderWithValues(Map<String, Long> map, BlockBuilder mapBlockBuilder)
Expand Down
Expand Up @@ -88,13 +88,13 @@ public void testCompactBlock()
Block incompactFiledBlock2 = new ByteArrayBlock(5, Optional.empty(), createExpectedValue(6).getBytes()); Block incompactFiledBlock2 = new ByteArrayBlock(5, Optional.empty(), createExpectedValue(6).getBytes());
boolean[] rowIsNull = {false, true, false, false, false, false}; boolean[] rowIsNull = {false, true, false, false, false, false};


assertCompact(fromFieldBlocks(new boolean[0], new Block[] {emptyBlock, emptyBlock})); assertCompact(fromFieldBlocks(0, Optional.empty(), new Block[] {emptyBlock, emptyBlock}));
assertCompact(fromFieldBlocks(rowIsNull, new Block[] {compactFieldBlock1, compactFieldBlock2})); assertCompact(fromFieldBlocks(rowIsNull.length, Optional.of(rowIsNull), new Block[] {compactFieldBlock1, compactFieldBlock2}));
// TODO: add test case for a sliced RowBlock // TODO: add test case for a sliced RowBlock


// underlying field blocks are not compact // underlying field blocks are not compact
testIncompactBlock(fromFieldBlocks(rowIsNull, new Block[] {incompactFiledBlock1, incompactFiledBlock2})); testIncompactBlock(fromFieldBlocks(rowIsNull.length, Optional.of(rowIsNull), new Block[] {incompactFiledBlock1, incompactFiledBlock2}));
testIncompactBlock(fromFieldBlocks(rowIsNull, new Block[] {incompactFiledBlock1, incompactFiledBlock2})); testIncompactBlock(fromFieldBlocks(rowIsNull.length, Optional.of(rowIsNull), new Block[] {incompactFiledBlock1, incompactFiledBlock2}));
} }


private void testWith(List<Type> fieldTypes, List<Object>[] expectedValues) private void testWith(List<Type> fieldTypes, List<Object>[] expectedValues)
Expand Down
Expand Up @@ -164,7 +164,7 @@ private static Block createArrayBlock(int positionCount, Block elementsBlock)
for (int i = 0; i < offsets.length; i++) { for (int i = 0; i < offsets.length; i++) {
offsets[i] = arraySize * i; offsets[i] = arraySize * i;
} }
return ArrayBlock.fromElementBlock(positionCount, new boolean[positionCount], offsets, elementsBlock); return ArrayBlock.fromElementBlock(positionCount, Optional.empty(), offsets, elementsBlock);
} }


private static Block createFixWidthValueBlock(int positionCount, int mapSize) private static Block createFixWidthValueBlock(int positionCount, int mapSize)
Expand Down
Expand Up @@ -164,7 +164,7 @@ private static Block createMapBlock(MapType mapType, int positionCount, Block ke
for (int i = 0; i < offsets.length; i++) { for (int i = 0; i < offsets.length; i++) {
offsets[i] = mapSize * i; offsets[i] = mapSize * i;
} }
return mapType.createBlockFromKeyValue(new boolean[positionCount], offsets, keyBlock, valueBlock); return mapType.createBlockFromKeyValue(Optional.empty(), offsets, keyBlock, valueBlock);
} }


private static Block createKeyBlock(int positionCount, List<String> keys) private static Block createKeyBlock(int positionCount, List<String> keys)
Expand Down
Expand Up @@ -175,7 +175,7 @@ private static Block createMapBlock(MapType mapType, int positionCount, Block ke
for (int i = 0; i < offsets.length; i++) { for (int i = 0; i < offsets.length; i++) {
offsets[i] = mapSize * i; offsets[i] = mapSize * i;
} }
return mapType.createBlockFromKeyValue(new boolean[positionCount], offsets, keyBlock, valueBlock); return mapType.createBlockFromKeyValue(Optional.empty(), offsets, keyBlock, valueBlock);
} }


private static Block createKeyBlock(int positionCount, List<String> keys) private static Block createKeyBlock(int positionCount, List<String> keys)
Expand Down
Expand Up @@ -108,7 +108,7 @@ private static Block createMapBlock(MapType mapType, int positionCount, Block ke
for (int i = 0; i < offsets.length; i++) { for (int i = 0; i < offsets.length; i++) {
offsets[i] = mapSize * i; offsets[i] = mapSize * i;
} }
return mapType.createBlockFromKeyValue(new boolean[positionCount], offsets, keyBlock, valueBlock); return mapType.createBlockFromKeyValue(Optional.empty(), offsets, keyBlock, valueBlock);
} }


private static Block createKeyBlock(int positionCount, int mapSize) private static Block createKeyBlock(int positionCount, int mapSize)
Expand Down
Expand Up @@ -99,7 +99,7 @@ public void setup()
Block[] fieldBlocks = fromFieldTypes.stream() Block[] fieldBlocks = fromFieldTypes.stream()
.map(type -> createBlock(POSITION_COUNT, type)) .map(type -> createBlock(POSITION_COUNT, type))
.toArray(Block[]::new); .toArray(Block[]::new);
Block rowBlock = fromFieldBlocks(new boolean[POSITION_COUNT], fieldBlocks); Block rowBlock = fromFieldBlocks(POSITION_COUNT, Optional.empty(), fieldBlocks);


page = new Page(rowBlock); page = new Page(rowBlock);
} }
Expand Down
Expand Up @@ -34,6 +34,7 @@
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.util.List; import java.util.List;
import java.util.Optional;


import static com.facebook.presto.orc.metadata.Stream.StreamKind.LENGTH; import static com.facebook.presto.orc.metadata.Stream.StreamKind.LENGTH;
import static com.facebook.presto.orc.metadata.Stream.StreamKind.PRESENT; import static com.facebook.presto.orc.metadata.Stream.StreamKind.PRESENT;
Expand Down Expand Up @@ -106,14 +107,15 @@ public Block readBlock(Type type)
// We will use the offsetVector as the buffer to read the length values from lengthStream, // We will use the offsetVector as the buffer to read the length values from lengthStream,
// and the length values will be converted in-place to an offset vector. // and the length values will be converted in-place to an offset vector.
int[] offsetVector = new int[nextBatchSize + 1]; int[] offsetVector = new int[nextBatchSize + 1];
boolean[] nullVector = new boolean[nextBatchSize]; boolean[] nullVector = null;
if (presentStream == null) { if (presentStream == null) {
if (lengthStream == null) { if (lengthStream == null) {
throw new OrcCorruptionException(streamDescriptor.getOrcDataSourceId(), "Value is not null but data stream is not present"); throw new OrcCorruptionException(streamDescriptor.getOrcDataSourceId(), "Value is not null but data stream is not present");
} }
lengthStream.nextIntVector(nextBatchSize, offsetVector, 0); lengthStream.nextIntVector(nextBatchSize, offsetVector, 0);
} }
else { else {
nullVector = new boolean[nextBatchSize];
int nullValues = presentStream.getUnsetBits(nextBatchSize, nullVector); int nullValues = presentStream.getUnsetBits(nextBatchSize, nullVector);
if (nullValues != nextBatchSize) { if (nullValues != nextBatchSize) {
if (lengthStream == null) { if (lengthStream == null) {
Expand Down Expand Up @@ -143,7 +145,7 @@ public Block readBlock(Type type)
else { else {
elements = elementType.createBlockBuilder(null, 0).build(); elements = elementType.createBlockBuilder(null, 0).build();
} }
Block arrayBlock = ArrayBlock.fromElementBlock(nextBatchSize, nullVector, offsetVector, elements); Block arrayBlock = ArrayBlock.fromElementBlock(nextBatchSize, Optional.ofNullable(nullVector), offsetVector, elements);


readOffset = 0; readOffset = 0;
nextBatchSize = 0; nextBatchSize = 0;
Expand Down
Expand Up @@ -35,6 +35,7 @@
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.util.List; import java.util.List;
import java.util.Optional;


import static com.facebook.presto.orc.metadata.Stream.StreamKind.LENGTH; import static com.facebook.presto.orc.metadata.Stream.StreamKind.LENGTH;
import static com.facebook.presto.orc.metadata.Stream.StreamKind.PRESENT; import static com.facebook.presto.orc.metadata.Stream.StreamKind.PRESENT;
Expand Down Expand Up @@ -110,7 +111,7 @@ public Block readBlock(Type type)
// We will use the offsetVector as the buffer to read the length values from lengthStream, // We will use the offsetVector as the buffer to read the length values from lengthStream,
// and the length values will be converted in-place to an offset vector. // and the length values will be converted in-place to an offset vector.
int[] offsetVector = new int[nextBatchSize + 1]; int[] offsetVector = new int[nextBatchSize + 1];
boolean[] nullVector = new boolean[nextBatchSize]; boolean[] nullVector = null;


if (presentStream == null) { if (presentStream == null) {
if (lengthStream == null) { if (lengthStream == null) {
Expand All @@ -119,6 +120,7 @@ public Block readBlock(Type type)
lengthStream.nextIntVector(nextBatchSize, offsetVector, 0); lengthStream.nextIntVector(nextBatchSize, offsetVector, 0);
} }
else { else {
nullVector = new boolean[nextBatchSize];
int nullValues = presentStream.getUnsetBits(nextBatchSize, nullVector); int nullValues = presentStream.getUnsetBits(nextBatchSize, nullVector);
if (nullValues != nextBatchSize) { if (nullValues != nextBatchSize) {
if (lengthStream == null) { if (lengthStream == null) {
Expand Down Expand Up @@ -165,7 +167,7 @@ public Block readBlock(Type type)
readOffset = 0; readOffset = 0;
nextBatchSize = 0; nextBatchSize = 0;


return mapType.createBlockFromKeyValue(nullVector, offsetVector, keyValueBlock[0], keyValueBlock[1]); return mapType.createBlockFromKeyValue(Optional.ofNullable(nullVector), offsetVector, keyValueBlock[0], keyValueBlock[1]);
} }


private static Block[] createKeyValueBlock(int positionCount, Block keys, Block values, int[] lengths) private static Block[] createKeyValueBlock(int positionCount, Block keys, Block values, int[] lengths)
Expand Down
Expand Up @@ -99,13 +99,14 @@ public Block readBlock(Type type)
} }
} }


boolean[] nullVector = new boolean[nextBatchSize]; boolean[] nullVector = null;
Block[] blocks; Block[] blocks;


if (presentStream == null) { if (presentStream == null) {
blocks = getBlocksForType(type, nextBatchSize); blocks = getBlocksForType(type, nextBatchSize);
} }
else { else {
nullVector = new boolean[nextBatchSize];
int nullValues = presentStream.getUnsetBits(nextBatchSize, nullVector); int nullValues = presentStream.getUnsetBits(nextBatchSize, nullVector);
if (nullValues != nextBatchSize) { if (nullValues != nextBatchSize) {
blocks = getBlocksForType(type, nextBatchSize - nullValues); blocks = getBlocksForType(type, nextBatchSize - nullValues);
Expand All @@ -125,7 +126,7 @@ public Block readBlock(Type type)
.count() == 1); .count() == 1);


// Struct is represented as a row block // Struct is represented as a row block
Block rowBlock = RowBlock.fromFieldBlocks(nullVector, blocks); Block rowBlock = RowBlock.fromFieldBlocks(nextBatchSize, Optional.ofNullable(nullVector), blocks);


readOffset = 0; readOffset = 0;
nextBatchSize = 0; nextBatchSize = 0;
Expand Down
Expand Up @@ -234,7 +234,7 @@ private void write(TempFile tempFile, Type writerType, List<String> data) throws
fieldBlocks[i] = blockBuilder.build(); fieldBlocks[i] = blockBuilder.build();
blockBuilder = blockBuilder.newBlockBuilderLike(null); blockBuilder = blockBuilder.newBlockBuilderLike(null);
} }
Block rowBlock = RowBlock.fromFieldBlocks(rowIsNull, fieldBlocks); Block rowBlock = RowBlock.fromFieldBlocks(rowIsNull.length, Optional.of(rowIsNull), fieldBlocks);
writer.write(new Page(rowBlock)); writer.write(new Page(rowBlock));
writer.close(); writer.close();
} }
Expand Down
Expand Up @@ -111,9 +111,10 @@ public Block copyRegion(int position, int length)
Block newValues = getRawElementBlock().copyRegion(startValueOffset, endValueOffset - startValueOffset); Block newValues = getRawElementBlock().copyRegion(startValueOffset, endValueOffset - startValueOffset);


int[] newOffsets = compactOffsets(getOffsets(), position + getOffsetBase(), length); int[] newOffsets = compactOffsets(getOffsets(), position + getOffsetBase(), length);
boolean[] newValueIsNull = compactArray(getValueIsNull(), position + getOffsetBase(), length); boolean[] valueIsNull = getValueIsNull();
boolean[] newValueIsNull = valueIsNull == null ? null : compactArray(valueIsNull, position + getOffsetBase(), length);


if (newValues == getRawElementBlock() && newOffsets == getOffsets() && newValueIsNull == getValueIsNull()) { if (newValues == getRawElementBlock() && newOffsets == getOffsets() && newValueIsNull == valueIsNull) {
return this; return this;
} }
return createArrayBlockInternal(0, length, newValueIsNull, newOffsets, newValues); return createArrayBlockInternal(0, length, newValueIsNull, newOffsets, newValues);
Expand Down Expand Up @@ -180,7 +181,8 @@ public long getEstimatedDataSizeForStats(int position)
public boolean isNull(int position) public boolean isNull(int position)
{ {
checkReadablePosition(position); checkReadablePosition(position);
return getValueIsNull()[position + getOffsetBase()]; boolean[] valueIsNull = getValueIsNull();
return valueIsNull == null ? false : valueIsNull[position + getOffsetBase()];
} }


public <T> T apply(ArrayBlockFunction<T> function, int position) public <T> T apply(ArrayBlockFunction<T> function, int position)
Expand Down
Expand Up @@ -18,6 +18,7 @@


import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.util.Arrays; import java.util.Arrays;
import java.util.Optional;


import static com.facebook.presto.spi.block.BlockUtil.checkArrayRange; import static com.facebook.presto.spi.block.BlockUtil.checkArrayRange;
import static com.facebook.presto.spi.block.BlockUtil.checkValidRegion; import static com.facebook.presto.spi.block.BlockUtil.checkValidRegion;
Expand Down Expand Up @@ -121,7 +122,7 @@ public Block copyPositions(int[] positions, int offset, int length)


Block newKeys = getRawKeyBlock().copyPositions(entriesPositions.elements(), 0, entriesPositions.size()); Block newKeys = getRawKeyBlock().copyPositions(entriesPositions.elements(), 0, entriesPositions.size());
Block newValues = getRawValueBlock().copyPositions(entriesPositions.elements(), 0, entriesPositions.size()); Block newValues = getRawValueBlock().copyPositions(entriesPositions.elements(), 0, entriesPositions.size());
return createMapBlockInternal(0, length, newMapIsNull, newOffsets, newKeys, newValues, newHashTable, keyType, keyBlockNativeEquals, keyNativeHashCode); return createMapBlockInternal(0, length, Optional.of(newMapIsNull), newOffsets, newKeys, newValues, newHashTable, keyType, keyBlockNativeEquals, keyNativeHashCode);
} }


@Override @Override
Expand All @@ -133,7 +134,7 @@ public Block getRegion(int position, int length)
return createMapBlockInternal( return createMapBlockInternal(
position + getOffsetBase(), position + getOffsetBase(),
length, length,
getMapIsNull(), Optional.ofNullable(getMapIsNull()),
getOffsets(), getOffsets(),
getRawKeyBlock(), getRawKeyBlock(),
getRawValueBlock(), getRawValueBlock(),
Expand Down Expand Up @@ -171,16 +172,17 @@ public Block copyRegion(int position, int length)
Block newValues = getRawValueBlock().copyRegion(startValueOffset, endValueOffset - startValueOffset); Block newValues = getRawValueBlock().copyRegion(startValueOffset, endValueOffset - startValueOffset);


int[] newOffsets = compactOffsets(getOffsets(), position + getOffsetBase(), length); int[] newOffsets = compactOffsets(getOffsets(), position + getOffsetBase(), length);
boolean[] newMapIsNull = compactArray(getMapIsNull(), position + getOffsetBase(), length); boolean[] mapIsNull = getMapIsNull();
boolean[] newMapIsNull = mapIsNull == null ? null : compactArray(mapIsNull, position + getOffsetBase(), length);
int[] newHashTable = compactArray(getHashTables(), startValueOffset * HASH_MULTIPLIER, (endValueOffset - startValueOffset) * HASH_MULTIPLIER); int[] newHashTable = compactArray(getHashTables(), startValueOffset * HASH_MULTIPLIER, (endValueOffset - startValueOffset) * HASH_MULTIPLIER);


if (newKeys == getRawKeyBlock() && newValues == getRawValueBlock() && newOffsets == getOffsets() && newMapIsNull == getMapIsNull() && newHashTable == getHashTables()) { if (newKeys == getRawKeyBlock() && newValues == getRawValueBlock() && newOffsets == getOffsets() && newMapIsNull == mapIsNull && newHashTable == getHashTables()) {
return this; return this;
} }
return createMapBlockInternal( return createMapBlockInternal(
0, 0,
length, length,
newMapIsNull, Optional.ofNullable(newMapIsNull),
newOffsets, newOffsets,
newKeys, newKeys,
newValues, newValues,
Expand Down Expand Up @@ -233,7 +235,7 @@ public Block getSingleValueBlock(int position)
return createMapBlockInternal( return createMapBlockInternal(
0, 0,
1, 1,
new boolean[] {isNull(position)}, Optional.of(new boolean[] {isNull(position)}),
new int[] {0, valueLength}, new int[] {0, valueLength},
newKeys, newKeys,
newValues, newValues,
Expand Down Expand Up @@ -269,7 +271,8 @@ public long getEstimatedDataSizeForStats(int position)
public boolean isNull(int position) public boolean isNull(int position)
{ {
checkReadablePosition(position); checkReadablePosition(position);
return getMapIsNull()[position + getOffsetBase()]; boolean[] mapIsNull = getMapIsNull();
return mapIsNull != null && mapIsNull[position + getOffsetBase()];
} }


private void checkReadablePosition(int position) private void checkReadablePosition(int position)
Expand Down

0 comments on commit df5131c

Please sign in to comment.