@Override
  public TsBlock next() throws Exception {
    if (retainedTsBlock != null) {
      return getResultFromRetainedTsBlock();
    }
    // start stopwatch
    long maxRuntime = operatorContext.getMaxRunTime().roundTo(TimeUnit.NANOSECONDS);
    long start = System.nanoTime();
    if (!buildFinished) {
      if (!buildSource.hasNextWithTimer()) {
        buildFinished = true;
      } else {
        TsBlock block = buildSource.nextWithTimer();
        if (block != null && !block.isEmpty()) {
          buildBlocks.add(block);
          memoryReservationManager.reserveMemoryCumulatively(block.getRetainedSizeInBytes());
        }
      }
      // probeSource could still be blocked by now, so we need to check it again
      return null;
    }
    cachedProbeBlock = cachedProbeBlock == null ? probeSource.nextWithTimer() : cachedProbeBlock;
    if (cachedProbeBlock == null || cachedProbeBlock.isEmpty()) {
      // TsBlock returned by probeSource is null or empty, we need to wait for another round
      cachedProbeBlock = null;
      return null;
    }
    while (probeIndex < cachedProbeBlock.getPositionCount()
        && System.nanoTime() - start < maxRuntime) {
      for (TsBlock buildBlock : buildBlocks) {
        appendValueToResult(probeIndex, buildBlock);
      }
      probeIndex++;
    }
    if (probeIndex == cachedProbeBlock.getPositionCount()) {
      probeIndex = 0;
      cachedProbeBlock = null;
    }
    if (resultBuilder.isEmpty()) {
      return null;
    }

    resultTsBlock =
        resultBuilder.build(
            new RunLengthEncodedColumn(TIME_COLUMN_TEMPLATE, resultBuilder.getPositionCount()));
    resultBuilder.reset();
    return checkTsBlockSizeAndGetResult();
  }
This Operator is used to implement the simple nested loop join algorithm for Cartesian product.
It is used to join two tables, one is the probe table and the other is the build table. For now,
the build table is assumed to be small enough to be cached in memory.(Produced by a scalar
subquery.) Scalar subquery is always the right child of PlanNode, so we can use right child of
JoinNode as the build table.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/join/SimpleNestedLoopCrossJoinOperator.java