[jOOQ/jOOQ#11470] Add support for the CORR aggregate functions

This includes:
- [jOOQ/jOOQ#11547] Emulate statistical aggregate functions
This commit is contained in:
Lukas Eder 2021-03-03 10:08:44 +01:00
parent ad6b037bf2
commit aca6a4181b
15 changed files with 236 additions and 26 deletions

View File

@ -282,4 +282,35 @@ implements
return this;
}
/**
* Apply this aggregate function's <code>FILTER</code> and <code>OVER</code>
* clauses to an argument aggregate function.
*/
final <U> Field<U> fo(AggregateFunction<U> function) {
WindowBeforeOverStep<U> s1 = filter != null ? function.filterWhere(filter) : function;
if (windowSpecification != null)
return s1.over(windowSpecification);
else if (windowDefinition != null)
return s1.over(windowDefinition);
else if (windowName != null)
return s1.over(windowName);
else
return s1;
}
/**
* Type safe <code>NVL2(y, x, null)</code> for REGR emulations.
*/
final <U extends Number> Field<U> x(Field<U> x, Field<? extends Number> y) {
return DSL.nvl2(y, x, DSL.NULL(x.getDataType()));
}
/**
* Type safe <code>NVL2(x, y, null)</code> for REGR emulations.
*/
final <U extends Number> Field<U> y(Field<? extends Number> x, Field<U> y) {
return DSL.nvl2(x, y, DSL.NULL(y.getDataType()));
}
}

View File

@ -87,4 +87,20 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedUntil(CUBRID, DERBY, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@Override
@SuppressWarnings("unchecked")
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect())) {
Field<? extends Number> x = (Field) getArguments().get(0);
Field<? extends Number> y = (Field) getArguments().get(1);
ctx.visit(fo(DSL.sum(x.times(y))).minus(fo(DSL.sum(x(x, y))).times(fo(DSL.sum(y(x, y)))).div(fo(DSL.count(x.plus(y))).cast(NUMERIC))).div(fo(DSL.count(x.plus(y))).cast(NUMERIC)));
}
else
super.accept(ctx);
}
}

View File

@ -87,4 +87,20 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedUntil(CUBRID, DERBY, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@Override
@SuppressWarnings("unchecked")
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect())) {
Field<? extends Number> x = (Field) getArguments().get(0);
Field<? extends Number> y = (Field) getArguments().get(1);
ctx.visit(fo(DSL.sum(x.times(y))).minus(fo(DSL.sum(x(x, y))).times(fo(DSL.sum(y(x, y)))).div(fo(DSL.count(x.plus(y))).cast(NUMERIC))).div(fo(DSL.count(x.plus(y))).cast(NUMERIC).minus(DSL.inline(1))));
}
else
super.accept(ctx);
}
}

View File

@ -18718,11 +18718,20 @@ public class DSL {
// Aggregate functions
// -------------------------------------------------------------------------
/**
* The <code>CORR</code> function.
*/
@NotNull
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
public static AggregateFunction<BigDecimal> corr(Field<? extends Number> y, Field<? extends Number> x) {
return new Corr(y, x);
}
/**
* The <code>COVAR_SAMP</code> function.
*/
@NotNull
@Support({ FIREBIRD, POSTGRES })
@Support
public static AggregateFunction<BigDecimal> covarSamp(Field<? extends Number> y, Field<? extends Number> x) {
return new CovarSamp(y, x);
}
@ -18731,7 +18740,7 @@ public class DSL {
* The <code>COVAR_POP</code> function.
*/
@NotNull
@Support({ FIREBIRD, POSTGRES })
@Support
public static AggregateFunction<BigDecimal> covarPop(Field<? extends Number> y, Field<? extends Number> x) {
return new CovarPop(y, x);
}
@ -18749,7 +18758,7 @@ public class DSL {
* The <code>REGR_AVG_X</code> function.
*/
@NotNull
@Support({ POSTGRES })
@Support
public static AggregateFunction<BigDecimal> regrAvgX(Field<? extends Number> y, Field<? extends Number> x) {
return new RegrAvgx(y, x);
}
@ -18758,7 +18767,7 @@ public class DSL {
* The <code>REGR_AVG_Y</code> function.
*/
@NotNull
@Support({ POSTGRES })
@Support
public static AggregateFunction<BigDecimal> regrAvgY(Field<? extends Number> y, Field<? extends Number> x) {
return new RegrAvgy(y, x);
}
@ -18767,7 +18776,7 @@ public class DSL {
* The <code>REGR_COUNT</code> function.
*/
@NotNull
@Support({ POSTGRES })
@Support
public static AggregateFunction<BigDecimal> regrCount(Field<? extends Number> y, Field<? extends Number> x) {
return new RegrCount(y, x);
}
@ -18776,7 +18785,7 @@ public class DSL {
* The <code>REGR_INTERCEPT</code> function.
*/
@NotNull
@Support({ POSTGRES })
@Support
public static AggregateFunction<BigDecimal> regrIntercept(Field<? extends Number> y, Field<? extends Number> x) {
return new RegrIntercept(y, x);
}
@ -18785,7 +18794,7 @@ public class DSL {
* The <code>REGR_R2</code> function.
*/
@NotNull
@Support({ POSTGRES })
@Support({ CUBRID, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
public static AggregateFunction<BigDecimal> regrR2(Field<? extends Number> y, Field<? extends Number> x) {
return new RegrR2(y, x);
}
@ -18794,7 +18803,7 @@ public class DSL {
* The <code>REGR_SLOPE</code> function.
*/
@NotNull
@Support({ POSTGRES })
@Support({ CUBRID, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
public static AggregateFunction<BigDecimal> regrSlope(Field<? extends Number> y, Field<? extends Number> x) {
return new RegrSlope(y, x);
}
@ -18803,7 +18812,7 @@ public class DSL {
* The <code>REGR_SXX</code> function.
*/
@NotNull
@Support({ POSTGRES })
@Support({ CUBRID, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
public static AggregateFunction<BigDecimal> regrSXX(Field<? extends Number> y, Field<? extends Number> x) {
return new RegrSxx(y, x);
}
@ -18812,7 +18821,7 @@ public class DSL {
* The <code>REGR_SXY</code> function.
*/
@NotNull
@Support({ POSTGRES })
@Support
public static AggregateFunction<BigDecimal> regrSXY(Field<? extends Number> y, Field<? extends Number> x) {
return new RegrSxy(y, x);
}
@ -18821,7 +18830,7 @@ public class DSL {
* The <code>REGR_SYY</code> function.
*/
@NotNull
@Support({ POSTGRES })
@Support({ CUBRID, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
public static AggregateFunction<BigDecimal> regrSYY(Field<? extends Number> y, Field<? extends Number> x) {
return new RegrSyy(y, x);
}

View File

@ -97,6 +97,7 @@ final class Names {
static final Name N_CONNECT_BY_IS_LEAF = unquotedName("connect_by_isleaf");
static final Name N_CONNECT_BY_ROOT = unquotedName("connect_by_root");
static final Name N_CONVERT = unquotedName("convert");
static final Name N_CORR = unquotedName("corr");
static final Name N_COS = unquotedName("cos");
static final Name N_COSH = unquotedName("cosh");
static final Name N_COT = unquotedName("cot");

View File

@ -107,6 +107,7 @@ import static org.jooq.impl.DSL.condition;
import static org.jooq.impl.DSL.constraint;
// ...
// ...
import static org.jooq.impl.DSL.corr;
import static org.jooq.impl.DSL.cos;
import static org.jooq.impl.DSL.cosh;
import static org.jooq.impl.DSL.cot;
@ -346,12 +347,6 @@ import static org.jooq.impl.DSL.xmlquery;
import static org.jooq.impl.DSL.xmltable;
import static org.jooq.impl.DSL.year;
import static org.jooq.impl.DSL.zero;
import static org.jooq.impl.JSONOnNull.ABSENT_ON_NULL;
import static org.jooq.impl.JSONOnNull.NULL_ON_NULL;
import static org.jooq.impl.Keywords.K_DELETE;
import static org.jooq.impl.Keywords.K_INSERT;
import static org.jooq.impl.Keywords.K_SELECT;
import static org.jooq.impl.Keywords.K_UPDATE;
import static org.jooq.impl.DefaultParseContext.Type.A;
import static org.jooq.impl.DefaultParseContext.Type.B;
import static org.jooq.impl.DefaultParseContext.Type.D;
@ -360,6 +355,12 @@ import static org.jooq.impl.DefaultParseContext.Type.N;
import static org.jooq.impl.DefaultParseContext.Type.S;
import static org.jooq.impl.DefaultParseContext.Type.X;
import static org.jooq.impl.DefaultParseContext.Type.Y;
import static org.jooq.impl.JSONOnNull.ABSENT_ON_NULL;
import static org.jooq.impl.JSONOnNull.NULL_ON_NULL;
import static org.jooq.impl.Keywords.K_DELETE;
import static org.jooq.impl.Keywords.K_INSERT;
import static org.jooq.impl.Keywords.K_SELECT;
import static org.jooq.impl.Keywords.K_UPDATE;
import static org.jooq.impl.SQLDataType.BIGINT;
import static org.jooq.impl.SQLDataType.INTEGER;
import static org.jooq.impl.SQLDataType.NVARCHAR;
@ -401,7 +402,6 @@ import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -430,7 +430,6 @@ import org.jooq.Catalog;
import org.jooq.CharacterSet;
import org.jooq.Collation;
import org.jooq.Comment;
import org.jooq.CommentOnFinalStep;
import org.jooq.CommentOnIsStep;
import org.jooq.CommonTableExpression;
import org.jooq.Comparator;
@ -508,7 +507,6 @@ import org.jooq.InsertOnDuplicateStep;
import org.jooq.InsertReturningStep;
import org.jooq.InsertSetStep;
import org.jooq.InsertValuesStepN;
import org.jooq.JSON;
import org.jooq.JSONArrayAggNullStep;
import org.jooq.JSONArrayAggOrderByStep;
import org.jooq.JSONArrayAggReturningStep;
@ -589,8 +587,6 @@ import org.jooq.UpdateWhereStep;
import org.jooq.User;
// ...
// ...
import org.jooq.VisitContext;
import org.jooq.VisitListener;
import org.jooq.WindowBeforeOverStep;
import org.jooq.WindowDefinition;
import org.jooq.WindowFromFirstLastStep;
@ -614,7 +610,6 @@ import org.jooq.conf.ParseWithMetaLookups;
import org.jooq.conf.RenderKeywordCase;
import org.jooq.conf.RenderNameCase;
import org.jooq.conf.RenderQuotedNames;
import org.jooq.conf.Settings;
import org.jooq.conf.SettingsTools;
import org.jooq.impl.ScopeStack.Value;
import org.jooq.impl.XMLParse.DocumentOrContent;
@ -625,8 +620,6 @@ import org.jooq.types.Interval;
import org.jooq.types.YearToMonth;
import org.jooq.types.YearToSecond;
import org.jetbrains.annotations.NotNull;
/**
* @author Lukas Eder
*/
@ -10717,6 +10710,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
parse(')');
switch (type) {
case CORR:
return corr(arg1, arg2);
case COVAR_POP:
return covarPop(arg1, arg2);
case COVAR_SAMP:
@ -13020,9 +13015,9 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
}
private static enum BinarySetFunctionType {
CORR,
COVAR_POP,
COVAR_SAMP,
// CORR,
REGR_SLOPE,
REGR_INTERCEPT,
REGR_COUNT,

View File

@ -87,4 +87,20 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@SuppressWarnings("unchecked")
@Override
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect())) {
Field<? extends Number> x = (Field) getArguments().get(0);
Field<? extends Number> y = (Field) getArguments().get(1);
ctx.visit(fo(DSL.avg(DSL.nvl2(x, y, DSL.NULL(NUMERIC)).cast(NUMERIC))));
}
else
super.accept(ctx);
}
}

View File

@ -87,4 +87,20 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@SuppressWarnings("unchecked")
@Override
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect())) {
Field<? extends Number> x = (Field) getArguments().get(0);
Field<? extends Number> y = (Field) getArguments().get(1);
ctx.visit(fo(DSL.avg(DSL.nvl2(y, x, DSL.NULL(NUMERIC)).cast(NUMERIC))));
}
else
super.accept(ctx);
}
}

View File

@ -87,4 +87,15 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@Override
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect()))
ctx.visit(fo(DSL.count(getArguments().get(0).plus(getArguments().get(1)))));
else
super.accept(ctx);
}
}

View File

@ -87,4 +87,20 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@SuppressWarnings("unchecked")
@Override
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect())) {
Field<? extends Number> x = (Field) getArguments().get(0);
Field<? extends Number> y = (Field) getArguments().get(1);
ctx.visit(fo(DSL.avg(x(x, y).cast(NUMERIC))).minus(fo(DSL.regrSlope(x, y)).times(fo(DSL.avg(y(x, y).cast(NUMERIC))))));
}
else
super.accept(ctx);
}
}

View File

@ -87,4 +87,24 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@SuppressWarnings("unchecked")
@Override
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect())) {
Field<? extends Number> x = (Field) getArguments().get(0);
Field<? extends Number> y = (Field) getArguments().get(1);
ctx.visit(DSL
.when(fo(DSL.varPop(y(x, y))).eq(inline(BigDecimal.ZERO)), DSL.NULL(NUMERIC))
.when(fo(DSL.varPop(x(x, y))).eq(inline(BigDecimal.ZERO)), inline(BigDecimal.ONE))
.else_(DSL.square(fo(DSL.corr(x, y))))
);
}
else
super.accept(ctx);
}
}

View File

@ -87,4 +87,20 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@SuppressWarnings("unchecked")
@Override
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect())) {
Field<? extends Number> x = (Field) getArguments().get(0);
Field<? extends Number> y = (Field) getArguments().get(1);
ctx.visit(fo(DSL.covarPop(x, y)).div(fo(DSL.varPop(y(x, y)))));
}
else
super.accept(ctx);
}
}

View File

@ -87,4 +87,20 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@SuppressWarnings("unchecked")
@Override
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect())) {
Field<? extends Number> x = (Field) getArguments().get(0);
Field<? extends Number> y = (Field) getArguments().get(1);
ctx.visit(fo(DSL.regrCount(x, y)).times(fo(DSL.varPop(y(x, y)))));
}
else
super.accept(ctx);
}
}

View File

@ -87,4 +87,20 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@SuppressWarnings("unchecked")
@Override
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect())) {
Field<? extends Number> x = (Field) getArguments().get(0);
Field<? extends Number> y = (Field) getArguments().get(1);
ctx.visit(fo(DSL.regrCount(x, y)).times(fo(DSL.covarPop(x, y))));
}
else
super.accept(ctx);
}
}

View File

@ -87,4 +87,19 @@ extends
private static final Set<SQLDialect> NO_SUPPORT_NATIVE = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, SQLITE);
@SuppressWarnings("unchecked")
@Override
public void accept(Context<?> ctx) {
if (NO_SUPPORT_NATIVE.contains(ctx.dialect())) {
Field<? extends Number> x = (Field) getArguments().get(0);
Field<? extends Number> y = (Field) getArguments().get(1);
ctx.visit(fo(DSL.regrCount(x, y)).times(fo(DSL.varPop(x(x, y)))));
}
else
super.accept(ctx);
}
}