[jOOQ/jOOQ#12465] DefaultAggregateFunction should be final

DefaultAggregateFunction historically is for simple aggregate
functions without extra functionality, such as MIN, MAX, COUNT, SUM,
AVG. It was then used as a base implementation for various others, which
should be extending AbstractAggregateFunction, instead.

This refactoring will simplify further QOM work
This commit is contained in:
Lukas Eder 2021-09-23 11:09:29 +02:00
parent 3cc898203a
commit a5533230c5
31 changed files with 123 additions and 119 deletions

View File

@ -53,10 +53,16 @@ import static org.jooq.SQLDialect.YUGABYTE;
import static org.jooq.impl.DSL.condition;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.zero;
import static org.jooq.impl.Keywords.K_DENSE_RANK;
import static org.jooq.impl.Keywords.K_DISTINCT;
import static org.jooq.impl.Keywords.K_FILTER;
import static org.jooq.impl.Keywords.K_FIRST;
import static org.jooq.impl.Keywords.K_KEEP;
import static org.jooq.impl.Keywords.K_LAST;
import static org.jooq.impl.Keywords.K_NULL;
import static org.jooq.impl.Keywords.K_ORDER_BY;
import static org.jooq.impl.Keywords.K_WHERE;
import static org.jooq.impl.Keywords.K_WITHIN_GROUP;
import static org.jooq.impl.Names.*;
import static org.jooq.impl.QueryPartCollectionView.wrap;
import static org.jooq.impl.SQLDataType.DOUBLE;
@ -113,6 +119,19 @@ implements
SortFieldList keepDenseRankOrderBy;
boolean first;
AbstractAggregateFunction(String name, DataType<T> type, Field<?>... arguments) {
this(false, name, type, arguments);
}
AbstractAggregateFunction(Name name, DataType<T> type, Field<?>... arguments) {
this(false, name, type, arguments);
}
AbstractAggregateFunction(boolean distinct, String name, DataType<T> type, Field<?>... arguments) {
this(distinct, DSL.unquotedName(name), type, arguments);
}
AbstractAggregateFunction(boolean distinct, Name name, DataType<T> type, Field<?>... arguments) {
super(name, type);
@ -124,6 +143,77 @@ implements
// XXX QueryPart API
// -------------------------------------------------------------------------
@Override
public /* final */ void accept(Context<?> ctx) {
toSQLArguments(ctx);
acceptKeepDenseRankOrderByClause(ctx);
acceptWithinGroupClause(ctx);
acceptFilterClause(ctx);
acceptOverClause(ctx);
}
/**
* Render <code>KEEP (DENSE_RANK [FIRST | LAST] ORDER BY {...})</code> clause
*/
private final void acceptKeepDenseRankOrderByClause(Context<?> ctx) {
if (!Tools.isEmpty(keepDenseRankOrderBy)) {
switch (ctx.family()) {
default:
ctx.sql(' ').visit(K_KEEP)
.sql(" (").visit(K_DENSE_RANK)
.sql(' ').visit(first ? K_FIRST : K_LAST)
.sql(' ').visit(K_ORDER_BY)
.sql(' ').visit(keepDenseRankOrderBy)
.sql(')');
break;
}
}
}
/**
* Render <code>WITHIN GROUP (ORDER BY ..)</code> clause
*/
final void acceptWithinGroupClause(Context<?> ctx) {
if (withinGroupOrderBy != null) {
switch (ctx.family()) {
default:
ctx.sql(' ').visit(K_WITHIN_GROUP)
.sql(" (").visit(K_ORDER_BY).sql(' ');
if (withinGroupOrderBy.isEmpty())
ctx.visit(K_NULL);
else
ctx.visit(withinGroupOrderBy);
ctx.sql(')');
break;
}
}
}
/**
* Render function arguments and argument modifiers
*/
private final void toSQLArguments(Context<?> ctx) {
acceptFunctionName(ctx);
ctx.sql('(');
acceptArguments0(ctx);
ctx.sql(')');
}
/* non-final */ void acceptFunctionName(Context<?> ctx) {

View File

@ -63,7 +63,7 @@ import java.util.*;
@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
final class AnyValue<T>
extends
DefaultAggregateFunction<T>
AbstractAggregateFunction<T>
{
AnyValue(

View File

@ -45,7 +45,7 @@ import org.jooq.Field;
/**
* @author Lukas Eder
*/
final class ArrayAgg<T> extends DefaultAggregateFunction<T[]> {
final class ArrayAgg<T> extends AbstractAggregateFunction<T[]> {
ArrayAgg(boolean distinct, Field<T> arg) {
super(distinct, N_ARRAY_AGG, arg.getDataType().getArrayDataType(), arg);

View File

@ -65,7 +65,7 @@ import java.util.stream.*;
@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
final class BitAndAgg<T extends Number>
extends
DefaultAggregateFunction<T>
AbstractAggregateFunction<T>
{
BitAndAgg(

View File

@ -65,7 +65,7 @@ import java.util.stream.*;
@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
final class BitOrAgg<T extends Number>
extends
DefaultAggregateFunction<T>
AbstractAggregateFunction<T>
{
BitOrAgg(

View File

@ -65,7 +65,7 @@ import java.util.stream.*;
@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
final class BitXorAgg<T extends Number>
extends
DefaultAggregateFunction<T>
AbstractAggregateFunction<T>
{
BitXorAgg(

View File

@ -51,7 +51,7 @@ import org.jooq.SQLDialect;
/**
* @author Lukas Eder
*/
final class BoolAnd extends DefaultAggregateFunction<Boolean> {
final class BoolAnd extends AbstractAggregateFunction<Boolean> {
private static final Set<SQLDialect> EMULATE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
private final Condition condition;

View File

@ -75,7 +75,7 @@ import org.jooq.SQLDialect;
/**
* @author Lukas Eder
*/
final class BoolOr extends DefaultAggregateFunction<Boolean> {
final class BoolOr extends AbstractAggregateFunction<Boolean> {
private static final Set<SQLDialect> EMULATE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
private final Condition condition;

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class Corr
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
Corr(

View File

@ -44,7 +44,7 @@ import org.jooq.UniqueKey;
/**
* @author Lukas Eder
*/
final class CountTable extends DefaultAggregateFunction<Integer> {
final class CountTable extends AbstractAggregateFunction<Integer> {
private final Table<?> table;

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class CovarPop
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
CovarPop(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class CovarSamp
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
CovarSamp(

View File

@ -38,17 +38,6 @@
package org.jooq.impl;
import static org.jooq.impl.Keywords.K_DENSE_RANK;
import static org.jooq.impl.Keywords.K_FILTER;
import static org.jooq.impl.Keywords.K_FIRST;
import static org.jooq.impl.Keywords.K_KEEP;
import static org.jooq.impl.Keywords.K_LAST;
import static org.jooq.impl.Keywords.K_NULL;
import static org.jooq.impl.Keywords.K_ORDER_BY;
import static org.jooq.impl.Keywords.K_WHERE;
import static org.jooq.impl.Keywords.K_WITHIN_GROUP;
import org.jooq.Context;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.Name;
@ -59,100 +48,25 @@ import org.jooq.Name;
*
* @author Lukas Eder
*/
class DefaultAggregateFunction<T> extends AbstractAggregateFunction<T> {
final class DefaultAggregateFunction<T> extends AbstractAggregateFunction<T> {
// -------------------------------------------------------------------------
// XXX Constructors
// -------------------------------------------------------------------------
DefaultAggregateFunction(String name, DataType<T> type, Field<?>... arguments) {
this(false, name, type, arguments);
super(name, type, arguments);
}
DefaultAggregateFunction(Name name, DataType<T> type, Field<?>... arguments) {
this(false, name, type, arguments);
super(name, type, arguments);
}
DefaultAggregateFunction(boolean distinct, String name, DataType<T> type, Field<?>... arguments) {
this(distinct, DSL.unquotedName(name), type, arguments);
super(distinct, name, type, arguments);
}
DefaultAggregateFunction(boolean distinct, Name name, DataType<T> type, Field<?>... arguments) {
super(distinct, name, type, arguments);
}
// -------------------------------------------------------------------------
// XXX QueryPart API
// -------------------------------------------------------------------------
@Override
public /* final */ void accept(Context<?> ctx) {
toSQLArguments(ctx);
acceptKeepDenseRankOrderByClause(ctx);
acceptWithinGroupClause(ctx);
acceptFilterClause(ctx);
acceptOverClause(ctx);
}
/**
* Render <code>KEEP (DENSE_RANK [FIRST | LAST] ORDER BY {...})</code> clause
*/
private final void acceptKeepDenseRankOrderByClause(Context<?> ctx) {
if (!Tools.isEmpty(keepDenseRankOrderBy)) {
switch (ctx.family()) {
default:
ctx.sql(' ').visit(K_KEEP)
.sql(" (").visit(K_DENSE_RANK)
.sql(' ').visit(first ? K_FIRST : K_LAST)
.sql(' ').visit(K_ORDER_BY)
.sql(' ').visit(keepDenseRankOrderBy)
.sql(')');
break;
}
}
}
/**
* Render <code>WITHIN GROUP (ORDER BY ..)</code> clause
*/
final void acceptWithinGroupClause(Context<?> ctx) {
if (withinGroupOrderBy != null) {
switch (ctx.family()) {
default:
ctx.sql(' ').visit(K_WITHIN_GROUP)
.sql(" (").visit(K_ORDER_BY).sql(' ');
if (withinGroupOrderBy.isEmpty())
ctx.visit(K_NULL);
else
ctx.visit(withinGroupOrderBy);
ctx.sql(')');
break;
}
}
}
/**
* Render function arguments and argument modifiers
*/
private final void toSQLArguments(Context<?> ctx) {
acceptFunctionName(ctx);
ctx.sql('(');
acceptArguments0(ctx);
ctx.sql(')');
}
}

View File

@ -86,7 +86,7 @@ import org.jooq.SQLDialect;
/**
* @author Lukas Eder
*/
final class ListAgg extends DefaultAggregateFunction<String> {
final class ListAgg extends AbstractAggregateFunction<String> {
private static final Set<SQLDialect> SET_GROUP_CONCAT_MAX_LEN = SQLDialect.supportedBy(MARIADB, MYSQL);
private static final Set<SQLDialect> SUPPORT_GROUP_CONCAT = SQLDialect.supportedBy(CUBRID, H2, HSQLDB, MARIADB, MYSQL, SQLITE);
private static final Set<SQLDialect> SUPPORT_STRING_AGG = SQLDialect.supportedBy(POSTGRES);

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class Median
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
Median(

View File

@ -56,7 +56,7 @@ import org.jooq.SQLDialect;
/**
* @author Lukas Eder
*/
final class Mode<T> extends DefaultAggregateFunction<T> {
final class Mode<T> extends AbstractAggregateFunction<T> {
private static final Set<SQLDialect> EMULATE_AS_ORDERED_SET_AGG = SQLDialect.supportedBy(H2, POSTGRES, YUGABYTE);
Mode(Field<T> arg) {

View File

@ -69,7 +69,7 @@ import org.jooq.XMLAggOrderByStep;
/**
* @author Lukas Eder
*/
final class MultisetAgg<R extends Record> extends DefaultAggregateFunction<Result<R>> {
final class MultisetAgg<R extends Record> extends AbstractAggregateFunction<Result<R>> {
private final AbstractRow<R> row;

View File

@ -52,7 +52,7 @@ import org.jooq.Field;
/**
* @author Lukas Eder
*/
final class RatioToReport extends DefaultAggregateFunction<BigDecimal> {
final class RatioToReport extends AbstractAggregateFunction<BigDecimal> {
private final Field<? extends Number> field;
RatioToReport(Field<? extends Number> field) {

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class RegrAvgx
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
RegrAvgx(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class RegrAvgy
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
RegrAvgy(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class RegrCount
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
RegrCount(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class RegrIntercept
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
RegrIntercept(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class RegrR2
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
RegrR2(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class RegrSlope
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
RegrSlope(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class RegrSxx
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
RegrSxx(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class RegrSxy
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
RegrSxy(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class RegrSyy
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
RegrSyy(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class StddevPop
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
StddevPop(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class StddevSamp
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
StddevSamp(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class VarPop
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
VarPop(

View File

@ -66,7 +66,7 @@ import java.math.BigDecimal;
@SuppressWarnings({ "rawtypes", "unused" })
final class VarSamp
extends
DefaultAggregateFunction<BigDecimal>
AbstractAggregateFunction<BigDecimal>
{
VarSamp(