@Override public <T> T getObject(int position, Class<T> clazz) { if (clazz != Block.class) { throw new IllegalArgumentException("clazz must be Block.class"); } checkReadablePosition(position); int startValueOffset = getOffset(position); int endValueOffset = getOffset(position + 1); return clazz.cast(getRawElementBlock().getRegion(startValueOffset, endValueOffset - startValueOffset)); }
@Override public BlockBuilder appendStructureInternal(Block block, int position) { if (!(block instanceof AbstractArrayBlock)) { throw new IllegalArgumentException(); } AbstractArrayBlock arrayBlock = (AbstractArrayBlock) block; BlockBuilder entryBuilder = beginBlockEntry(); int startValueOffset = arrayBlock.getOffset(position); int endValueOffset = arrayBlock.getOffset(position + 1); for (int i = startValueOffset; i < endValueOffset; i++) { if (arrayBlock.getRawElementBlock().isNull(i)) { entryBuilder.appendNull(); } else { arrayBlock.getRawElementBlock().writePositionTo(i, entryBuilder); } } closeEntry(); return this; }
public <T> T apply(ArrayBlockFunction<T> function, int position) { checkReadablePosition(position); int startValueOffset = getOffset(position); int endValueOffset = getOffset(position + 1); return function.apply(getRawElementBlock(), startValueOffset, endValueOffset - startValueOffset); }
@Override public long getPositionsSizeInBytes(boolean[] positions) { checkValidPositions(positions, getPositionCount()); boolean[] used = new boolean[getRawElementBlock().getPositionCount()]; int usedPositionCount = 0; for (int i = 0; i < positions.length; ++i) { if (positions[i]) { usedPositionCount++; int valueStart = getOffsets()[getOffsetBase() + i]; int valueEnd = getOffsets()[getOffsetBase() + i + 1]; for (int j = valueStart; j < valueEnd; ++j) { used[j] = true; } } } return getRawElementBlock().getPositionsSizeInBytes(used) + ((Integer.BYTES + Byte.BYTES) * (long) usedPositionCount); }
public static ColumnarArray toColumnarArray(Block block) { requireNonNull(block, "block is null"); if (block instanceof DictionaryBlock) { return toColumnarArray((DictionaryBlock) block); } if (block instanceof RunLengthEncodedBlock) { return toColumnarArray((RunLengthEncodedBlock) block); } if (!(block instanceof AbstractArrayBlock)) { throw new IllegalArgumentException("Invalid array block: " + block.getClass().getName()); } AbstractArrayBlock arrayBlock = (AbstractArrayBlock) block; Block elementsBlock = arrayBlock.getRawElementBlock(); // trim elements to just visible region int elementsOffset = 0; int elementsLength = 0; if (arrayBlock.getPositionCount() > 0) { elementsOffset = arrayBlock.getOffset(0); elementsLength = arrayBlock.getOffset(arrayBlock.getPositionCount()) - elementsOffset; } elementsBlock = elementsBlock.getRegion(elementsOffset, elementsLength); return new ColumnarArray(block, arrayBlock.getOffsetBase(), arrayBlock.getOffsets(), elementsBlock); }
@Override public long getEstimatedDataSizeForStats(int position) { checkReadablePosition(position); if (isNull(position)) { return 0; } int startValueOffset = getOffset(position); int endValueOffset = getOffset(position + 1); Block rawElementBlock = getRawElementBlock(); long size = 0; for (int i = startValueOffset; i < endValueOffset; i++) { size += rawElementBlock.getEstimatedDataSizeForStats(i); } return size; }
@Override public Block getRegion(int position, int length) { int positionCount = getPositionCount(); checkValidRegion(positionCount, position, length); return createArrayBlockInternal( position + getOffsetBase(), length, getValueIsNull(), getOffsets(), getRawElementBlock()); }
@Override public Block getSingleValueBlock(int position) { checkReadablePosition(position); int startValueOffset = getOffset(position); int valueLength = getOffset(position + 1) - startValueOffset; Block newValues = getRawElementBlock().copyRegion(startValueOffset, valueLength); return createArrayBlockInternal( 0, 1, new boolean[] {isNull(position)}, new int[] {0, valueLength}, newValues); }
@Override public long getRegionSizeInBytes(int position, int length) { int positionCount = getPositionCount(); checkValidRegion(positionCount, position, length); int valueStart = getOffsets()[getOffsetBase() + position]; int valueEnd = getOffsets()[getOffsetBase() + position + length]; return getRawElementBlock().getRegionSizeInBytes(valueStart, valueEnd - valueStart) + ((Integer.BYTES + Byte.BYTES) * (long) length); }
@Override public Block copyRegion(int position, int length) { int positionCount = getPositionCount(); checkValidRegion(positionCount, position, length); int startValueOffset = getOffset(position); int endValueOffset = getOffset(position + length); Block newValues = getRawElementBlock().copyRegion(startValueOffset, endValueOffset - startValueOffset); int[] newOffsets = compactOffsets(getOffsets(), position + getOffsetBase(), length); boolean[] valueIsNull = getValueIsNull(); boolean[] newValueIsNull = valueIsNull == null ? null : compactArray(valueIsNull, position + getOffsetBase(), length); if (newValues == getRawElementBlock() && newOffsets == getOffsets() && newValueIsNull == valueIsNull) { return this; } return createArrayBlockInternal(0, length, newValueIsNull, newOffsets, newValues); }
@Override public void writeBlock(BlockEncodingSerde blockEncodingSerde, SliceOutput sliceOutput, Block block) { AbstractArrayBlock arrayBlock = (AbstractArrayBlock) block; int positionCount = arrayBlock.getPositionCount(); int offsetBase = arrayBlock.getOffsetBase(); int[] offsets = arrayBlock.getOffsets(); int valuesStartOffset = offsets[offsetBase]; int valuesEndOffset = offsets[offsetBase + positionCount]; Block values = arrayBlock.getRawElementBlock().getRegion(valuesStartOffset, valuesEndOffset - valuesStartOffset); blockEncodingSerde.writeBlock(sliceOutput, values); sliceOutput.appendInt(positionCount); for (int position = 0; position < positionCount + 1; position++) { sliceOutput.writeInt(offsets[offsetBase + position] - valuesStartOffset); } encodeNullsAsBits(sliceOutput, block); }
@Override public Block copyPositions(int[] positions, int offset, int length) { checkArrayRange(positions, offset, length); int[] newOffsets = new int[length + 1]; boolean[] newValueIsNull = new boolean[length]; IntArrayList valuesPositions = new IntArrayList(); int newPosition = 0; for (int i = offset; i < offset + length; ++i) { int position = positions[i]; if (isNull(position)) { newValueIsNull[newPosition] = true; newOffsets[newPosition + 1] = newOffsets[newPosition]; } else { int valuesStartOffset = getOffset(position); int valuesEndOffset = getOffset(position + 1); int valuesLength = valuesEndOffset - valuesStartOffset; newOffsets[newPosition + 1] = newOffsets[newPosition] + valuesLength; for (int elementIndex = valuesStartOffset; elementIndex < valuesEndOffset; elementIndex++) { valuesPositions.add(elementIndex); } } newPosition++; } Block newValues = getRawElementBlock().copyPositions(valuesPositions.elements(), 0, valuesPositions.size()); return createArrayBlockInternal(0, length, newValueIsNull, newOffsets, newValues); }
@Override public <T> T getObject(int position, Class<T> clazz) { if (clazz != Block.class) { throw new IllegalArgumentException("clazz must be Block.class"); } checkReadablePosition(position); int startValueOffset = getOffset(position); int endValueOffset = getOffset(position + 1); return clazz.cast(getRawElementBlock().getRegion(startValueOffset, endValueOffset - startValueOffset)); }
public <T> T apply(ArrayBlockFunction<T> function, int position) { checkReadablePosition(position); int startValueOffset = getOffset(position); int endValueOffset = getOffset(position + 1); return function.apply(getRawElementBlock(), startValueOffset, endValueOffset - startValueOffset); }
@Override public long getEstimatedDataSizeForStats(int position) { checkReadablePosition(position); if (isNull(position)) { return 0; } int startValueOffset = getOffset(position); int endValueOffset = getOffset(position + 1); Block rawElementBlock = getRawElementBlock(); long size = 0; for (int i = startValueOffset; i < endValueOffset; i++) { size += rawElementBlock.getEstimatedDataSizeForStats(i); } return size; }
@Override public Block getRegion(int position, int length) { int positionCount = getPositionCount(); checkValidRegion(positionCount, position, length); return createArrayBlockInternal( position + getOffsetBase(), length, getValueIsNull(), getOffsets(), getRawElementBlock()); }
@Override public Block getSingleValueBlock(int position) { checkReadablePosition(position); int startValueOffset = getOffset(position); int valueLength = getOffset(position + 1) - startValueOffset; Block newValues = getRawElementBlock().copyRegion(startValueOffset, valueLength); return createArrayBlockInternal( 0, 1, new boolean[] {isNull(position)}, new int[] {0, valueLength}, newValues); }
@Override public long getRegionSizeInBytes(int position, int length) { int positionCount = getPositionCount(); checkValidRegion(positionCount, position, length); int valueStart = getOffsets()[getOffsetBase() + position]; int valueEnd = getOffsets()[getOffsetBase() + position + length]; return getRawElementBlock().getRegionSizeInBytes(valueStart, valueEnd - valueStart) + ((Integer.BYTES + Byte.BYTES) * (long) length); }
@Override public Block copyRegion(int position, int length) { int positionCount = getPositionCount(); checkValidRegion(positionCount, position, length); int startValueOffset = getOffset(position); int endValueOffset = getOffset(position + length); Block newValues = getRawElementBlock().copyRegion(startValueOffset, endValueOffset - startValueOffset); int[] newOffsets = compactOffsets(getOffsets(), position + getOffsetBase(), length); boolean[] valueIsNull = getValueIsNull(); boolean[] newValueIsNull = valueIsNull == null ? null : compactArray(valueIsNull, position + getOffsetBase(), length); if (newValues == getRawElementBlock() && newOffsets == getOffsets() && newValueIsNull == valueIsNull) { return this; } return createArrayBlockInternal(0, length, newValueIsNull, newOffsets, newValues); }
@Override public void writeBlock(BlockEncodingSerde blockEncodingSerde, SliceOutput sliceOutput, Block block) { AbstractArrayBlock arrayBlock = (AbstractArrayBlock) block; int positionCount = arrayBlock.getPositionCount(); int offsetBase = arrayBlock.getOffsetBase(); int[] offsets = arrayBlock.getOffsets(); int valuesStartOffset = offsets[offsetBase]; int valuesEndOffset = offsets[offsetBase + positionCount]; Block values = arrayBlock.getRawElementBlock().getRegion(valuesStartOffset, valuesEndOffset - valuesStartOffset); blockEncodingSerde.writeBlock(sliceOutput, values); sliceOutput.appendInt(positionCount); for (int position = 0; position < positionCount + 1; position++) { sliceOutput.writeInt(offsets[offsetBase + position] - valuesStartOffset); } encodeNullsAsBits(sliceOutput, block); }