@Test
  public void testConsumeAllChildrenPipelineBuilder2() throws IllegalPathException {
    TypeProvider typeProvider = new TypeProvider();
    FullOuterTimeJoinNode fullOuterTimeJoinNode = initFullOuterTimeJoinNode(typeProvider, 4);
    LocalExecutionPlanContext context = createLocalExecutionPlanContext(typeProvider);
    context.setDegreeOfParallelism(2);

    List<Operator> childrenOperator =
        operatorTreeGenerator.dealWithConsumeAllChildrenPipelineBreaker(
            fullOuterTimeJoinNode, context);
    // The number of pipeline is 1, since parent pipeline hasn't joined
    assertEquals(1, context.getPipelineNumber());

    // Validate the first pipeline
    assertEquals(3, childrenOperator.size());
    assertEquals(3, fullOuterTimeJoinNode.getChildren().size());
    for (int i = 0; i < 2; i++) {
      assertEquals(SeriesScanOperator.class, childrenOperator.get(i).getClass());
      assertEquals(SeriesScanNode.class, fullOuterTimeJoinNode.getChildren().get(i).getClass());
    }
    assertEquals(ExchangeOperator.class, childrenOperator.get(2).getClass());

    // Validate the changes of node structure
    assertEquals(
        "root.sg.d0.s1", fullOuterTimeJoinNode.getChildren().get(0).getOutputColumnNames().get(0));
    assertEquals(
        "root.sg.d1.s1", fullOuterTimeJoinNode.getChildren().get(1).getOutputColumnNames().get(0));
    assertEquals(
        FullOuterTimeJoinNode.class, fullOuterTimeJoinNode.getChildren().get(2).getClass());

    // Validate the second pipeline
    FullOuterTimeJoinNode subFullOuterTimeJoinNode =
        (FullOuterTimeJoinNode) fullOuterTimeJoinNode.getChildren().get(2);
    assertEquals(2, subFullOuterTimeJoinNode.getChildren().size());
    assertEquals(
        "root.sg.d2.s1",
        subFullOuterTimeJoinNode.getChildren().get(0).getOutputColumnNames().get(0));
    assertEquals(
        "root.sg.d3.s1",
        subFullOuterTimeJoinNode.getChildren().get(1).getOutputColumnNames().get(0));

    // Validate the number exchange operator
    assertEquals(1, context.getExchangeSumNum());

    // Validate PipelineMemoryEstimator
    try (Operator root =
        fullOuterTimeJoinNode.accept(
            operatorTreeGenerator, createLocalExecutionPlanContext(typeProvider))) {
      PipelineMemoryEstimator rootPipelineMemoryEstimator =
          context.constructPipelineMemoryEstimator(root, null, fullOuterTimeJoinNode, -1);
      assertEquals(
          ConsumeAllChildrenPipelineMemoryEstimator.class, rootPipelineMemoryEstimator.getClass());
      // test calculateEstimatedMemory
      assertEquals(
          root.calculateMaxPeekMemoryWithCounter()
              + rootPipelineMemoryEstimator.getChildren().stream()
                  .map(PipelineMemoryEstimator::calculateEstimatedRunningMemorySize)
                  .reduce(0L, Long::sum),
          rootPipelineMemoryEstimator.calculateEstimatedRunningMemorySize());

      List<PipelineMemoryEstimator> childrenPipelineMemoryEstimators =
          rootPipelineMemoryEstimator.getChildren();
      assertEquals(1, childrenPipelineMemoryEstimators.size());
      for (int i = 0; i < 1; i++) {
        assertEquals(
            ConsumeAllChildrenPipelineMemoryEstimator.class,
            childrenPipelineMemoryEstimators.get(i).getClass());
        assertEquals(
            FullOuterTimeJoinOperator.class,
            childrenPipelineMemoryEstimators.get(i).getRoot().getClass());
      }
    } catch (Exception e) {
      e.printStackTrace();
      fail();
    }
  }
This test will test dop = 2. Expected result is two pipelines:

<p>The first is: TimeJoin1 - [SeriesScan1, SeriesScan0, ExchangeOperator];

<p>The second is: ExchangeOperator - TimeJoin1-1[SeriesScan2, SeriesScan3].
iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/PipelineBuilderTest.java