[jOOQ/jOOQ#11670] Add support for GROUP BY DISTINCT
This commit is contained in:
parent
1fe17ecbaa
commit
c81cf7bd59
@ -192,6 +192,7 @@ public interface Select<R extends Record> extends ResultQuery<R>, TableLike<R>,
|
||||
@NotNull Select<?> $from(MList<? extends Table<?>> from);
|
||||
@Nullable Condition $where();
|
||||
@NotNull MList<? extends GroupField> $groupBy();
|
||||
boolean $groupByDistinct();
|
||||
@Nullable Condition $having();
|
||||
@NotNull MList<? extends WindowDefinition> $window();
|
||||
@Nullable Condition $qualify();
|
||||
|
||||
@ -37,8 +37,11 @@
|
||||
*/
|
||||
package org.jooq;
|
||||
|
||||
import org.jooq.impl.DSL;
|
||||
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@ -123,4 +126,26 @@ public interface SelectGroupByStep<R extends Record> extends SelectHavingStep<R>
|
||||
@NotNull @CheckReturnValue
|
||||
@Support
|
||||
SelectHavingStep<R> groupBy(Collection<? extends GroupField> fields);
|
||||
|
||||
/**
|
||||
* Add a <code>GROUP BY DISTINCT</code> clause to the query
|
||||
* <p>
|
||||
* This is mostly useful when combined with
|
||||
* {@link DSL#groupingSets(Field[]...)} to remove duplicate grouping set
|
||||
* results prior to aggregation and projection.
|
||||
*/
|
||||
@NotNull @CheckReturnValue
|
||||
@Support({ POSTGRES })
|
||||
SelectHavingStep<R> groupByDistinct(GroupField... fields);
|
||||
|
||||
/**
|
||||
* Add a <code>GROUP BY DISTINCT</code> clause to the query
|
||||
* <p>
|
||||
* This is mostly useful when combined with
|
||||
* {@link DSL#groupingSets(Field[]...)} to remove duplicate grouping set
|
||||
* results prior to aggregation and projection.
|
||||
*/
|
||||
@NotNull @CheckReturnValue
|
||||
@Support({ POSTGRES })
|
||||
SelectHavingStep<R> groupByDistinct(Collection<? extends GroupField> fields);
|
||||
}
|
||||
|
||||
@ -71,6 +71,7 @@ import static org.jooq.SQLDialect.POSTGRES;
|
||||
// ...
|
||||
// ...
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.SQLITE;
|
||||
// ...
|
||||
// ...
|
||||
@ -341,6 +342,16 @@ public interface SelectQuery<R extends Record> extends Select<R>, ConditionProvi
|
||||
@Support
|
||||
void addGroupBy(Collection<? extends GroupField> fields);
|
||||
|
||||
/**
|
||||
* Specifies the <code>GROUP BY DISTINCT</code> clause.
|
||||
* <p>
|
||||
* This is mostly useful when combined with
|
||||
* {@link DSL#groupingSets(Field[]...)} to remove duplicate grouping set
|
||||
* results prior to aggregation and projection.
|
||||
*/
|
||||
@Support({ POSTGRES })
|
||||
void setGroupByDistinct(boolean groupByDistinct);
|
||||
|
||||
/**
|
||||
* Adds a new condition to the having clause of the query, connecting it
|
||||
* with each other with {@link Operator#AND}.
|
||||
|
||||
@ -43,6 +43,7 @@ package org.jooq.impl;
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
// ...
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.impl.Keywords.K_IN;
|
||||
import static org.jooq.impl.Keywords.K_INOUT;
|
||||
import static org.jooq.impl.Keywords.K_OUT;
|
||||
|
||||
@ -1775,6 +1775,9 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
List<GroupField> groupBy;
|
||||
|
||||
if (parseKeywordIf("GROUP BY")) {
|
||||
if (!parseKeywordIf("ALL") && parseKeywordIf("DISTINCT"))
|
||||
result.setGroupByDistinct(true);
|
||||
|
||||
if (parseIf('(')) {
|
||||
parse(')');
|
||||
result.addGroupBy();
|
||||
|
||||
@ -702,6 +702,20 @@ implements
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SelectImpl groupByDistinct(GroupField... fields) {
|
||||
getQuery().addGroupBy(fields);
|
||||
getQuery().setGroupByDistinct(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SelectImpl groupByDistinct(Collection<? extends GroupField> fields) {
|
||||
getQuery().addGroupBy(fields);
|
||||
getQuery().setGroupByDistinct(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@ -3395,6 +3409,11 @@ implements
|
||||
return getDelegate().$groupBy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean $groupByDistinct() {
|
||||
return getDelegate().$groupByDistinct();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition $having() {
|
||||
return getDelegate().$having();
|
||||
|
||||
@ -389,6 +389,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
private final ConditionProviderImpl condition;
|
||||
private boolean grouping;
|
||||
private QueryPartList<GroupField> groupBy;
|
||||
private boolean groupByDistinct;
|
||||
private final ConditionProviderImpl having;
|
||||
private WindowList window;
|
||||
private final ConditionProviderImpl qualify;
|
||||
@ -524,6 +525,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private final SelectQueryImpl<R> copyTo(CopyClause clause, boolean scalarSelect, SelectQueryImpl<R> result) {
|
||||
@ -552,6 +554,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
|
||||
result.grouping = grouping;
|
||||
result.groupBy = groupBy;
|
||||
result.groupByDistinct = groupByDistinct;
|
||||
result.having.setWhere(having.getWhere());
|
||||
if (window != null)
|
||||
result.addWindow(window);
|
||||
@ -2402,8 +2405,12 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
|
||||
if (grouping) {
|
||||
context.formatSeparator()
|
||||
.visit(K_GROUP_BY)
|
||||
.separatorRequired(true);
|
||||
.visit(K_GROUP_BY);
|
||||
|
||||
if (groupByDistinct)
|
||||
context.sql(' ').visit(K_DISTINCT);
|
||||
|
||||
context.separatorRequired(true);
|
||||
|
||||
// [#1665] Empty GROUP BY () clauses need parentheses
|
||||
if (Tools.isEmpty(groupBy)) {
|
||||
@ -3854,6 +3861,9 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
|
||||
final void setGrouping() {
|
||||
grouping = true;
|
||||
|
||||
if (groupBy == null)
|
||||
groupBy = new QueryPartList<>();
|
||||
}
|
||||
|
||||
final ConditionProviderImpl getWhere(Context<?> ctx) {
|
||||
@ -4149,13 +4159,15 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
@Override
|
||||
public final void addGroupBy(Collection<? extends GroupField> fields) {
|
||||
setGrouping();
|
||||
|
||||
if (groupBy == null)
|
||||
groupBy = new QueryPartList<>();
|
||||
|
||||
groupBy.addAll(fields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setGroupByDistinct(boolean groupByDistinct) {
|
||||
setGrouping();
|
||||
this.groupByDistinct = groupByDistinct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void addGroupBy(GroupField... fields) {
|
||||
addGroupBy(Arrays.asList(fields));
|
||||
@ -4543,6 +4555,11 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
return groupBy == null ? QueryPartList.emptyList() : groupBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean $groupByDistinct() {
|
||||
return groupByDistinct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition $having() {
|
||||
return having;
|
||||
@ -4594,16 +4611,18 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
$from(),
|
||||
$where(),
|
||||
$groupBy(),
|
||||
$groupByDistinct(),
|
||||
$having(),
|
||||
$window(),
|
||||
$qualify(),
|
||||
$orderBy(),
|
||||
(cte, s, d, f, c, g, h, w, q, o) -> {
|
||||
(cte, s, d, f, c, g, gd, h, w, q, o) -> {
|
||||
SelectQueryImpl<?> r = new SelectQueryImpl<>(configuration(), cte, d);
|
||||
r.select.addAll(s);
|
||||
r.from.addAll(f);
|
||||
r.condition.addConditions(extractCondition(c));
|
||||
r.groupBy = g;
|
||||
r.groupByDistinct = gd;
|
||||
r.having.addConditions(extractCondition(h));
|
||||
r.addWindow(w);
|
||||
r.qualify.addConditions(extractCondition(q));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user