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;
}