public static PlanMatchPattern aggregationTreeDeviceViewTableScan(
      GroupingSetDescriptor groupingSets,
      List<String> preGroupedSymbols,
      Optional<Symbol> groupId,
      AggregationNode.Step step,
      String expectedTableName,
      List<String> outputSymbols,
      Set<String> assignmentsKeys) {
    PlanMatchPattern result = node(AggregationTreeDeviceViewScanNode.class);

    result.with(
        new AggregationDeviceTableScanMatcher(
            groupingSets,
            preGroupedSymbols,
            ImmutableList.of(),
            groupId,
            step,
            expectedTableName,
            Optional.empty(),
            outputSymbols,
            assignmentsKeys));

    outputSymbols.forEach(
        outputSymbol ->
            result.withAlias(outputSymbol, new ColumnReference(expectedTableName, outputSymbol)));
    return result;
  }
Matches to any tree of nodes with children matching to given source matchers.
anyTree(tableScan("nation")) - will match to any plan which all leafs contain any node
containing table scan from nation table.

<p>Note: anyTree does not match zero nodes. E.g. output(anyTree(tableScan)) will NOT match
TableScan node followed by OutputNode.
iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/assertions/PlanMatchPattern.java