@Override
  public TsBlock next() throws Exception {
    if (retainedTsBlock != null) {
      return getResultFromRetainedTsBlock();
    }
    tsBlockBuilder.reset();
    if (!prepareInput()) {
      return null;
    }

    // End time for returned TsBlock this time, it's the min/max end time among all the children
    // TsBlocks order by asc/desc
    long currentEndTime = 0;
    boolean init = false;

    // Get TsBlock for each input, put their time stamp into TimeSelector and then use the min Time
    // among all the input TsBlock as the current output TsBlock's endTime.
    for (int i = 0; i < inputOperatorsCount; i++) {
      if (!noMoreTsBlocks[i]) {
        // Update the currentEndTime if the TsBlock is not empty
        currentEndTime =
            init
                ? comparator.getCurrentEndTime(currentEndTime, inputTsBlocks[i].getEndTime())
                : inputTsBlocks[i].getEndTime();
        init = true;
      }
    }

    if (timeSelector.isEmpty()) {
      // Return empty TsBlock
      TsBlockBuilder emptyTsBlockBuilder = new TsBlockBuilder(0, dataTypes);
      return emptyTsBlockBuilder.build();
    }

    TimeColumnBuilder timeBuilder = tsBlockBuilder.getTimeColumnBuilder();
    long currentTime;
    do {
      currentTime = timeSelector.pollFirst();
      timeBuilder.writeLong(currentTime);

      appendOneRow(currentTime);
      tsBlockBuilder.declarePosition();

      prepareForTimeHeap();

    } while (comparator.lessThan(currentTime, currentEndTime) && !timeSelector.isEmpty());

    resultTsBlock = tsBlockBuilder.build();
    return checkTsBlockSizeAndGetResult();
  }
This field indicates each data type for output columns(not including time column) of
TimeJoinOperator its size should be equal to outputColumnCount.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/join/FullOuterTimeJoinOperator.java