private boolean needNewSubQuery()

in core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java [1964:2060]


    private boolean needNewSubQuery(
        @UnknownInitialization Result this,
        RelNode rel, List<Clause> clauses,
        Set<Clause> expectedClauses) {
      if (clauses.isEmpty()) {
        return false;
      }
      final Clause maxClause = Collections.max(clauses);
      // If old and new clause are equal and belong to below set,
      // then new SELECT wrap is not required
      final Set<Clause> nonWrapSet = ImmutableSet.of(Clause.SELECT);
      for (Clause clause : expectedClauses) {
        if (maxClause.ordinal() > clause.ordinal()
            || (maxClause == clause
                && !nonWrapSet.contains(clause))) {
          return true;
        }
      }

      if (rel instanceof Project
          && clauses.contains(Clause.HAVING)
          && dialect.getConformance().isHavingAlias()) {
        return true;
      }

      if (rel instanceof Aggregate
          && (clauses.contains(Clause.ORDER_BY)
          || clauses.contains(Clause.FETCH)
          || clauses.contains(Clause.OFFSET))) {
        return true;
      }

      // Cannot merge two window functions
      boolean containsOver = containsOver(node);
      if (rel instanceof Project
          && ((Project) rel).containsOver()
          && containsOver) {
        return true;
      }

      if (rel instanceof Window && containsOver) {
        return true;
      }

      if (rel instanceof Project
          && clauses.contains(Clause.ORDER_BY)
          && dialect.getConformance().isSortByOrdinal()
          && hasSortByOrdinal(node)) {
        // Cannot merge a Project that contains sort by ordinal under it.
        return true;
      }

      if (rel instanceof Project) {
        Project project = (Project) rel;
        RelNode input = project.getInput();
        if (input instanceof Aggregate) {
          // Cannot merge because "select 1 from t"
          // is different from "select 1 from (select count(1) from t)"
          //
          // Some databases don't allow "GROUP BY ()". On those databases,
          //   SELECT MIN(1) FROM t
          // is valid and
          //   SELECT 1 FROM t GROUP BY ()
          // is not. So, if an aggregate has no group keys we can only remove
          // the subquery if there is at least one aggregate function.
          // See RelToSqlConverter.buildAggregate.
          final Aggregate aggregate = (Aggregate) input;
          final ImmutableBitSet fieldsUsed =
              RelOptUtil.InputFinder.bits(project.getProjects(), null);
          final boolean hasAggregate =
              !aggregate.getGroupSet().isEmpty()
                  || !aggregate.getAggCallList().isEmpty();
          if (hasAggregate && fieldsUsed.isEmpty()) {
            return true;
          }
        }
      }

      if (rel instanceof Aggregate) {
        final Aggregate agg = (Aggregate) rel;
        final boolean hasNestedAgg =
            hasNested(agg, SqlImplementor::isAggregate);
        final boolean hasNestedWindowedAgg =
            hasNested(agg, SqlImplementor::isWindowedAggregate);
        if (!dialect.supportsNestedAggregations()
            && (hasNestedAgg || hasNestedWindowedAgg)) {
          return true;
        }

        if (clauses.contains(Clause.GROUP_BY)) {
          // Avoid losing the distinct attribute of inner aggregate.
          return !hasNestedAgg || Aggregate.isNotGrandTotal(agg);
        }
      }

      return false;
    }