public TsBlock buildTsBlock()

in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java [997:1140]


  public TsBlock buildTsBlock(
      int floatPrecision,
      List<TSEncoding> encodingList,
      List<TimeRange> timeColumnDeletion,
      List<List<TimeRange>> deletionList,
      boolean ignoreAllNullRows) {
    TsBlockBuilder builder = new TsBlockBuilder(dataTypes);
    // Time column
    TimeColumnBuilder timeBuilder = builder.getTimeColumnBuilder();
    int validRowCount = 0;

    // duplicated time or deleted time are all invalid, true if we don't need this row
    boolean[] timeInvalidInfo = null;
    int[] deleteCursor = {0};
    // time column
    for (int sortedRowIndex = 0; sortedRowIndex < rowCount; sortedRowIndex++) {
      // skip empty row
      if (allValueColDeletedMap != null
          && allValueColDeletedMap.isMarked(getValueIndex(sortedRowIndex))) {
        continue;
      }
      if (isTimeDeleted(sortedRowIndex)) {
        continue;
      }
      int nextRowIndex = sortedRowIndex + 1;
      while (nextRowIndex < rowCount
          && ((allValueColDeletedMap != null
                  && allValueColDeletedMap.isMarked(getValueIndex(nextRowIndex)))
              || (isTimeDeleted(nextRowIndex)))) {
        nextRowIndex++;
      }
      long timestamp = getTime(sortedRowIndex);
      if ((nextRowIndex == rowCount || timestamp != getTime(nextRowIndex))
          && !isPointDeleted(timestamp, timeColumnDeletion, deleteCursor)) {
        timeBuilder.writeLong(getTime(sortedRowIndex));
        validRowCount++;
      } else {
        if (Objects.isNull(timeInvalidInfo)) {
          timeInvalidInfo = new boolean[rowCount];
        }
        timeInvalidInfo[sortedRowIndex] = true;
      }
      sortedRowIndex = nextRowIndex - 1;
    }

    boolean[] hasAnyNonNullValue = new boolean[validRowCount];
    int columnCount = dataTypes.size();
    int currentWriteRowIndex;
    // value columns
    for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
      deleteCursor = new int[] {0};
      // Pair of Time and Index
      Pair<Long, Integer> lastValidPointIndexForTimeDupCheck = null;
      if (Objects.nonNull(timeInvalidInfo)) {
        lastValidPointIndexForTimeDupCheck = new Pair<>(Long.MIN_VALUE, null);
      }
      ColumnBuilder valueBuilder = builder.getColumnBuilder(columnIndex);
      currentWriteRowIndex = 0;
      for (int sortedRowIndex = 0; sortedRowIndex < rowCount; sortedRowIndex++) {
        // skip empty row
        if ((allValueColDeletedMap != null
                && allValueColDeletedMap.isMarked(getValueIndex(sortedRowIndex)))
            || (isTimeDeleted(sortedRowIndex))) {
          continue;
        }
        // skip time duplicated or totally deleted rows
        if (Objects.nonNull(timeInvalidInfo)) {
          if (!isNullValue(getValueIndex(sortedRowIndex), columnIndex)) {
            lastValidPointIndexForTimeDupCheck.left = getTime(sortedRowIndex);
            lastValidPointIndexForTimeDupCheck.right = getValueIndex(sortedRowIndex);
          }
          if (timeInvalidInfo[sortedRowIndex]) {
            continue;
          }
        }
        // The part of code solves the following problem:
        // Time: 1,2,2,3
        // Value: 1,2,null,null
        // When rowIndex:1, pair(min,null), timeDuplicateInfo:false, write(T:1,V:1)
        // When rowIndex:2, pair(2,2), timeDuplicateInfo:true, skip writing value
        // When rowIndex:3, pair(2,2), timeDuplicateInfo:false, T:2==pair.left:2, write(T:2,V:2)
        // When rowIndex:4, pair(2,2), timeDuplicateInfo:false, T:3!=pair.left:2, write(T:3,V:null)
        int originRowIndex;
        if (Objects.nonNull(lastValidPointIndexForTimeDupCheck)
            && (getTime(sortedRowIndex) == lastValidPointIndexForTimeDupCheck.left)) {
          originRowIndex = lastValidPointIndexForTimeDupCheck.right;
        } else {
          originRowIndex = getValueIndex(sortedRowIndex);
        }
        if (isNullValue(originRowIndex, columnIndex)
            || isPointDeleted(
                getTime(sortedRowIndex),
                Objects.isNull(deletionList) ? null : deletionList.get(columnIndex),
                deleteCursor)) {
          valueBuilder.appendNull();
          currentWriteRowIndex++;
          continue;
        }
        hasAnyNonNullValue[currentWriteRowIndex++] = true;
        switch (dataTypes.get(columnIndex)) {
          case BOOLEAN:
            valueBuilder.writeBoolean(getBooleanByValueIndex(originRowIndex, columnIndex));
            break;
          case INT32:
          case DATE:
            valueBuilder.writeInt(getIntByValueIndex(originRowIndex, columnIndex));
            break;
          case INT64:
          case TIMESTAMP:
            valueBuilder.writeLong(getLongByValueIndex(originRowIndex, columnIndex));
            break;
          case FLOAT:
            valueBuilder.writeFloat(
                roundValueWithGivenPrecision(
                    getFloatByValueIndex(originRowIndex, columnIndex),
                    floatPrecision,
                    encodingList.get(columnIndex)));
            break;
          case DOUBLE:
            valueBuilder.writeDouble(
                roundValueWithGivenPrecision(
                    getDoubleByValueIndex(originRowIndex, columnIndex),
                    floatPrecision,
                    encodingList.get(columnIndex)));
            break;
          case TEXT:
          case BLOB:
          case STRING:
            valueBuilder.writeBinary(getBinaryByValueIndex(originRowIndex, columnIndex));
            break;
          default:
            break;
        }
      }
    }
    builder.declarePositions(validRowCount);
    TsBlock tsBlock = builder.build();
    if (!ignoreAllNullRows || !needRebuildTsBlock(hasAnyNonNullValue)) {
      return tsBlock;
    } else {
      // if exist all null rows, at most have validRowCount - 1 valid rows
      return reBuildTsBlock(hasAnyNonNullValue, validRowCount, columnCount, tsBlock);
    }
  }