[jOOQ/jOOQ#12910] Add DSL.emptyGroupingSet(): GroupField for explicit

empty grouping sets

This also fixes:

- [jOOQ/jOOQ#12908] Select:: loses GROUP BY clause
This commit is contained in:
Lukas Eder 2022-01-21 10:45:36 +01:00
parent 3009752b64
commit 0e9a2abeca
5 changed files with 57 additions and 65 deletions

View File

@ -65,6 +65,14 @@ import org.jooq.impl.QOM;
*
* @author Lukas Eder
*/
public /* sealed */ interface GroupField extends QueryPart /* permits Table, Field, QOM.Rollup, QOM.Cube, QOM.GroupingSets */ {
}
public /* sealed */ interface GroupField
extends
QueryPart
/* permits
Table,
Field,
QOM.EmptyGroupingSet,
QOM.Rollup,
QOM.Cube,
QOM.GroupingSets */
{}

View File

@ -24265,6 +24265,26 @@ public class DSL {
// XXX Construction of GROUPING SET functions
// ------------------------------------------------------------------------
/**
* Create a GROUPING SETS(field1, field2, .., fieldn) grouping field where
* each grouping set only consists of a single field.
* <p>
* Please check the SQL Server documentation for a very nice explanation of
* <code>CUBE</code>, <code>ROLLUP</code>, and <code>GROUPING SETS</code>
* clauses in grouping contexts: <a
* href="http://msdn.microsoft.com/en-US/library/bb522495.aspx"
* >http://msdn.microsoft.com/en-US/library/bb522495.aspx</a>
*
* @param fields The fields that are part of the <code>GROUPING SETS</code>
* function
* @return A field to be used in a <code>GROUP BY</code> clause
*/
@NotNull
@Support({ POSTGRES })
public static GroupField emptyGroupingSet() {
return EmptyGroupingSet.INSTANCE;
}
/**
* Create a ROLLUP(field1, field2, .., fieldn) grouping field.
*
@ -24279,16 +24299,6 @@ public class DSL {
/**
* Create a ROLLUP(field1, field2, .., fieldn) grouping field.
* <p>
* This has been observed to work with the following databases:
* <ul>
* <li>DB2</li>
* <li>MySQL (emulated using the GROUP BY .. WITH ROLLUP clause)</li>
* <li>Oracle</li>
* <li>PostgreSQL 9.5</li>
* <li>SQL Server</li>
* <li>Sybase SQL Anywhere</li>
* </ul>
* <p>
* Please check the SQL Server documentation for a very nice explanation of
* <code>CUBE</code>, <code>ROLLUP</code>, and <code>GROUPING SETS</code>
* clauses in grouping contexts: <a
@ -24319,15 +24329,6 @@ public class DSL {
/**
* Create a CUBE(field1, field2, .., fieldn) grouping field.
* <p>
* This has been observed to work with the following databases:
* <ul>
* <li>DB2</li>
* <li>Oracle</li>
* <li>PostgreSQL 9.5</li>
* <li>SQL Server</li>
* <li>Sybase SQL Anywhere</li>
* </ul>
* <p>
* Please check the SQL Server documentation for a very nice explanation of
* <code>CUBE</code>, <code>ROLLUP</code>, and <code>GROUPING SETS</code>
* clauses in grouping contexts: <a
@ -24348,15 +24349,6 @@ public class DSL {
* Create a GROUPING SETS(field1, field2, .., fieldn) grouping field where
* each grouping set only consists of a single field.
* <p>
* This has been observed to work with the following databases:
* <ul>
* <li>DB2</li>
* <li>Oracle</li>
* <li>PostgreSQL 9.5</li>
* <li>SQL Server</li>
* <li>Sybase SQL Anywhere</li>
* </ul>
* <p>
* Please check the SQL Server documentation for a very nice explanation of
* <code>CUBE</code>, <code>ROLLUP</code>, and <code>GROUPING SETS</code>
* clauses in grouping contexts: <a
@ -24378,15 +24370,6 @@ public class DSL {
* Create a GROUPING SETS((field1a, field1b), (field2a), .., (fieldna,
* fieldnb)) grouping field.
* <p>
* This has been observed to work with the following databases:
* <ul>
* <li>DB2</li>
* <li>Oracle</li>
* <li>PostgreSQL 9.5</li>
* <li>SQL Server</li>
* <li>Sybase SQL Anywhere</li>
* </ul>
* <p>
* Please check the SQL Server documentation for a very nice explanation of
* <code>CUBE</code>, <code>ROLLUP</code>, and <code>GROUPING SETS</code>
* clauses in grouping contexts: <a
@ -24408,15 +24391,6 @@ public class DSL {
* Create a GROUPING SETS((field1a, field1b), (field2a), .., (fieldna,
* fieldnb)) grouping field.
* <p>
* This has been observed to work with the following databases:
* <ul>
* <li>DB2</li>
* <li>Oracle</li>
* <li>PostgreSQL 9.5</li>
* <li>SQL Server</li>
* <li>Sybase SQL Anywhere</li>
* </ul>
* <p>
* Please check the SQL Server documentation for a very nice explanation of
* <code>CUBE</code>, <code>ROLLUP</code>, and <code>GROUPING SETS</code>
* clauses in grouping contexts: <a

View File

@ -40,6 +40,7 @@ package org.jooq.impl;
import static java.util.Arrays.asList;
import static org.jooq.SQLDialect.*;
import static org.jooq.impl.DSL.emptyGroupingSet;
import static org.jooq.impl.DSL.groupingSets;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.Tools.EMPTY_FIELD;
@ -128,7 +129,7 @@ final class GroupFieldList extends QueryPartList<GroupField> {
// Few dialects support the SQL standard "grand total" (i.e. empty grouping set)
else
ctx.sql("()");
ctx.visit(emptyGroupingSet());
}
@Override

View File

@ -526,6 +526,14 @@ public final class QOM {
// XXX: SelectFields, GroupFields and SortFields
// -------------------------------------------------------------------------
public /* sealed */ interface EmptyGroupingSet
extends
GroupField,
UEmpty
/* permits
org.jooq.impl.EmptyGroupingSet */
{}
// Can't seal these types yet because of https://bugs.eclipse.org/bugs/show_bug.cgi?id=577872
public /* non-sealed */ interface Rollup

View File

@ -121,6 +121,7 @@ import static org.jooq.impl.CombineOperator.UNION_ALL;
import static org.jooq.impl.CommonTableExpressionList.markTopLevelCteAndAccept;
import static org.jooq.impl.DSL.asterisk;
import static org.jooq.impl.DSL.createTable;
import static org.jooq.impl.DSL.emptyGroupingSet;
import static org.jooq.impl.DSL.falseCondition;
import static org.jooq.impl.DSL.generateSeries;
import static org.jooq.impl.DSL.inline;
@ -366,8 +367,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
private final TableList from;
private final ConditionProviderImpl condition;
private boolean grouping;
private GroupFieldList groupBy;
private final GroupFieldList groupBy;
private boolean groupByDistinct;
private final ConditionProviderImpl having;
private WindowList window;
@ -416,6 +416,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
this.groupBy = new GroupFieldList();
this.having = new ConditionProviderImpl();
this.qualify = new ConditionProviderImpl();
this.orderBy = new SortFieldList();
@ -504,7 +505,6 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
private final SelectQueryImpl<R> copyTo(CopyClause clause, boolean scalarSelect, SelectQueryImpl<R> result) {
@ -531,8 +531,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
result.grouping = grouping;
result.groupBy = groupBy;
result.groupBy.addAll(groupBy);
result.groupByDistinct = groupByDistinct;
result.having.setWhere(having.getWhere());
if (window != null)
@ -2380,7 +2379,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
// --------------------------
context.start(SELECT_GROUP_BY);
if (grouping) {
if (!getGroupBy().isEmpty()) {
context.formatSeparator()
.visit(K_GROUP_BY);
@ -3800,13 +3799,6 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
return from;
}
final void setGrouping() {
grouping = true;
if (groupBy == null)
groupBy = new GroupFieldList();
}
final ConditionProviderImpl getWhere(Context<?> ctx) {
ConditionProviderImpl result = new ConditionProviderImpl();
@ -3890,6 +3882,10 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
final GroupFieldList getGroupBy() {
return groupBy;
}
final ConditionProviderImpl getHaving() {
return having;
}
@ -4099,13 +4095,18 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
@Override
public final void addGroupBy(Collection<? extends GroupField> fields) {
setGrouping();
// [#12910] For backwards compatibility, adding empty GROUP BY lists to
// a blank GROUP BY clause must maintain empty grouping set
// semantics
if (fields.isEmpty())
groupBy.add(emptyGroupingSet());
groupBy.addAll(fields);
}
@Override
public final void setGroupByDistinct(boolean groupByDistinct) {
setGrouping();
this.groupByDistinct = groupByDistinct;
}