Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.trino.spi.block;
import jakarta.annotation.Nullable;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.ObjLongConsumer;
import static io.airlift.slice.SizeOf.instanceSize;
import static io.airlift.slice.SizeOf.sizeOf;
import static io.trino.spi.block.BlockUtil.arraySame;
import static io.trino.spi.block.BlockUtil.checkArrayRange;
import static io.trino.spi.block.BlockUtil.checkReadablePosition;
import static io.trino.spi.block.BlockUtil.checkValidPositions;
import static io.trino.spi.block.BlockUtil.checkValidRegion;
import static io.trino.spi.block.BlockUtil.compactArray;
import static io.trino.spi.block.BlockUtil.ensureBlocksAreLoaded;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
public final class RowBlock
implements ValueBlock
{
private static final int INSTANCE_SIZE = instanceSize(RowBlock.class);
private final int positionCount;
@Nullable
private final boolean[] rowIsNull;
/**
* Field blocks have the same position count as this row block. The field value of a null row must be null.
*/
private final Block[] fieldBlocks;
private final List fieldBlocksList;
private final int fixedSizePerRow;
private volatile long sizeInBytes = -1;
/**
* Create a row block directly from field blocks. The returned RowBlock will not contain any null rows, although the fields may contain null values.
*/
public static RowBlock fromFieldBlocks(int positionCount, Block[] fieldBlocks)
{
return createRowBlockInternal(positionCount, null, fieldBlocks);
}
/**
* Create a row block directly from field blocks that are not null-suppressed. The field value of a null row must be null.
*/
public static RowBlock fromNotNullSuppressedFieldBlocks(int positionCount, Optional rowIsNullOptional, Block[] fieldBlocks)
{
// verify that field values for null rows are null
if (rowIsNullOptional.isPresent()) {
boolean[] rowIsNull = rowIsNullOptional.get();
checkArrayRange(rowIsNull, 0, positionCount);
for (int fieldIndex = 0; fieldIndex < fieldBlocks.length; fieldIndex++) {
Block field = fieldBlocks[fieldIndex];
// LazyBlock may not have loaded the field yet
if (!(field instanceof LazyBlock lazyBlock) || lazyBlock.isLoaded()) {
for (int position = 0; position < positionCount; position++) {
if (rowIsNull[position] && !field.isNull(position)) {
throw new IllegalArgumentException(format("Field value for null row must be null: field %s, position %s", fieldIndex, position));
}
}
}
}
}
return createRowBlockInternal(positionCount, rowIsNullOptional.orElse(null), fieldBlocks);
}
static RowBlock createRowBlockInternal(int positionCount, @Nullable boolean[] rowIsNull, Block[] fieldBlocks)
{
int fixedSize = Byte.BYTES;
for (Block fieldBlock : fieldBlocks) {
OptionalInt fieldFixedSize = fieldBlock.fixedSizeInBytesPerPosition();
if (fieldFixedSize.isEmpty()) {
// found a block without a single per-position size
fixedSize = -1;
break;
}
fixedSize += fieldFixedSize.getAsInt();
}
return new RowBlock(positionCount, rowIsNull, fieldBlocks, fixedSize);
}
/**
* Use createRowBlockInternal or fromFieldBlocks instead of this method. The caller of this method is assumed to have
* validated the arguments with validateConstructorArguments.
*/
private RowBlock(int positionCount, @Nullable boolean[] rowIsNull, Block[] fieldBlocks, int fixedSizePerRow)
{
if (positionCount < 0) {
throw new IllegalArgumentException("positionCount is negative");
}
if (rowIsNull != null && rowIsNull.length < positionCount) {
throw new IllegalArgumentException("rowIsNull length is less than positionCount");
}
requireNonNull(fieldBlocks, "fieldBlocks is null");
if (fieldBlocks.length == 0) {
throw new IllegalArgumentException("Row block must contain at least one field");
}
for (int i = 0; i < fieldBlocks.length; i++) {
if (positionCount != fieldBlocks[i].getPositionCount()) {
throw new IllegalArgumentException("Expected field %s to have %s positions but has %s positions".formatted(i, positionCount, fieldBlocks[i].getPositionCount()));
}
}
this.positionCount = positionCount;
this.rowIsNull = positionCount == 0 ? null : rowIsNull;
this.fieldBlocks = fieldBlocks;
this.fieldBlocksList = List.of(fieldBlocks);
this.fixedSizePerRow = fixedSizePerRow;
}
Block[] getRawFieldBlocks()
{
return fieldBlocks;
}
public List getFieldBlocks()
{
return fieldBlocksList;
}
public Block getFieldBlock(int fieldIndex)
{
return fieldBlocks[fieldIndex];
}
@Override
public boolean mayHaveNull()
{
return rowIsNull != null;
}
boolean[] getRawRowIsNull()
{
return rowIsNull;
}
@Override
public int getPositionCount()
{
return positionCount;
}
@Override
public long getSizeInBytes()
{
if (sizeInBytes >= 0) {
return sizeInBytes;
}
long sizeInBytes = Byte.BYTES * (long) positionCount;
boolean hasUnloadedBlocks = false;
for (Block fieldBlock : fieldBlocks) {
sizeInBytes += fieldBlock.getSizeInBytes();
hasUnloadedBlocks = hasUnloadedBlocks || !fieldBlock.isLoaded();
}
if (!hasUnloadedBlocks) {
this.sizeInBytes = sizeInBytes;
}
return sizeInBytes;
}
@Override
public long getRetainedSizeInBytes()
{
long retainedSizeInBytes = INSTANCE_SIZE + sizeOf(rowIsNull);
for (Block fieldBlock : fieldBlocks) {
retainedSizeInBytes += fieldBlock.getRetainedSizeInBytes();
}
return retainedSizeInBytes;
}
@Override
public void retainedBytesForEachPart(ObjLongConsumer