diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index bfc6892242..1585e9b1ec 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -2488,7 +2488,6 @@ final class SelectQueryImpl extends AbstractResultQuery imp - ; List semiAntiJoinPredicates = null; @@ -2606,7 +2605,8 @@ final class SelectQueryImpl extends AbstractResultQuery imp // -------------------------- context.start(SELECT_GROUP_BY); - if (!getGroupBy().isEmpty() || getHaving().hasWhere() && NO_IMPLICIT_GROUP_BY_ON_HAVING.contains(context.dialect())) { + ConditionProviderImpl having0 = getHaving(context); + if (!getGroupBy().isEmpty() || having0.hasWhere() && NO_IMPLICIT_GROUP_BY_ON_HAVING.contains(context.dialect())) { context.formatSeparator() .visit(K_GROUP_BY); @@ -2641,11 +2641,11 @@ final class SelectQueryImpl extends AbstractResultQuery imp // ------------- context.start(SELECT_HAVING); - if (getHaving().hasWhere()) + if (having0.hasWhere()) context.formatSeparator() .visit(K_HAVING) .sql(' ') - .visit(getHaving()); + .visit(having0); context.end(SELECT_HAVING); @@ -4272,7 +4272,8 @@ final class SelectQueryImpl extends AbstractResultQuery imp // - There is a SEEK clause (obvious case) // - There are no unions (union is nested in derived table // and SEEK predicate is applied outside). See [#7459] - if (!getOrderBy().isEmpty() && !getSeek().isEmpty() && unionOp.isEmpty()) + // [#15820] We're not grouping + if (!isGrouping() && !getOrderBy().isEmpty() && !getSeek().isEmpty() && unionOp.isEmpty()) result.addConditions(getSeekCondition(ctx)); // [#13639] Add JOIN predicates generated by path expressions in FROM clause. @@ -4405,12 +4406,32 @@ final class SelectQueryImpl extends AbstractResultQuery imp + final boolean isGrouping() { + + // [#15820] TODO: The presence of any aggregate function also implies at least GROUP BY () + return !groupBy.isEmpty() || having.hasWhere(); + } + final GroupFieldList getGroupBy() { return groupBy; } - final ConditionProviderImpl getHaving() { - return having; + final ConditionProviderImpl getHaving(Context ctx) { + ConditionProviderImpl result = new ConditionProviderImpl(); + + if (having.hasWhere()) + result.addConditions(having.getWhere()); + + // Apply SEEK predicates in the WHERE clause only if: + // - There is an ORDER BY clause (SEEK is non-deterministic) + // - There is a SEEK clause (obvious case) + // - There are no unions (union is nested in derived table + // and SEEK predicate is applied outside). See [#7459] + // [#15820] We're not grouping + if (isGrouping() && !getOrderBy().isEmpty() && !getSeek().isEmpty() && unionOp.isEmpty()) + result.addConditions(getSeekCondition(ctx)); + + return result; } final ConditionProviderImpl getQualify() { @@ -4646,32 +4667,32 @@ final class SelectQueryImpl extends AbstractResultQuery imp @Override public final void addHaving(Condition conditions) { - getHaving().addConditions(conditions); + having.addConditions(conditions); } @Override public final void addHaving(Condition... conditions) { - getHaving().addConditions(conditions); + having.addConditions(conditions); } @Override public final void addHaving(Collection conditions) { - getHaving().addConditions(conditions); + having.addConditions(conditions); } @Override public final void addHaving(Operator operator, Condition conditions) { - getHaving().addConditions(operator, conditions); + having.addConditions(operator, conditions); } @Override public final void addHaving(Operator operator, Condition... conditions) { - getHaving().addConditions(operator, conditions); + having.addConditions(operator, conditions); } @Override public final void addHaving(Operator operator, Collection conditions) { - getHaving().addConditions(operator, conditions); + having.addConditions(operator, conditions); } @Override