[jOOQ/jOOQ#10644] Add Settings.transformUnneededArithmeticExpressions to

optimise arithmetic prior to SQL generation

- Added INTERNAL implementation to functions
- Fixed recursive behaviour
- Implement this for unaryMinus() (negation)
This commit is contained in:
Lukas Eder 2020-09-22 14:32:05 +02:00
parent f57d5d8af4
commit e232a06e84
30 changed files with 188 additions and 63 deletions

View File

@ -329,7 +329,7 @@ abstract class AbstractField<T> extends AbstractTypedNamed<T> implements Field<T
@Override
public final Field<T> neg() {
return new Neg<>(this, ExpressionOperator.SUBTRACT);
return new Neg<>(this, false, ExpressionOperator.SUBTRACT);
}
@Override

View File

@ -39,6 +39,10 @@ package org.jooq.impl;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.two;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Internal.ineg;
import static org.jooq.impl.Names.N_ACOS;
import java.math.BigDecimal;
@ -72,6 +76,15 @@ final class Acos extends AbstractField<BigDecimal> {
default:
ctx.visit(N_ACOS).sql('(').visit(arg).sql(')');
break;

View File

@ -38,6 +38,10 @@
package org.jooq.impl;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Internal.ineg;
import static org.jooq.impl.Names.N_ASIN;
import java.math.BigDecimal;
@ -71,6 +75,11 @@ final class Asin extends AbstractField<BigDecimal> {
default:
ctx.visit(N_ASIN).sql('(').visit(arg).sql(')');
break;

View File

@ -39,6 +39,9 @@ package org.jooq.impl;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.two;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Names.N_COSH;
import java.math.BigDecimal;
@ -86,7 +89,13 @@ final class Cosh extends AbstractField<BigDecimal> {
case MARIADB:
case MYSQL:
case POSTGRES:
ctx.visit(DSL.exp(argument.mul(two())).add(one()).div(DSL.exp(argument).mul(two())));
ctx.visit(idiv(
iadd(
DSL.exp(imul(argument, two())),
one()
),
imul(DSL.exp(argument), two())
));
break;
default:

View File

@ -37,6 +37,7 @@
*/
package org.jooq.impl;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Names.N_COT;
import java.math.BigDecimal;

View File

@ -87,6 +87,10 @@ import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
// ...
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Keywords.K_CUBE;
import static org.jooq.impl.Keywords.K_GROUPING_SETS;
import static org.jooq.impl.Names.N_IF;
@ -18857,7 +18861,7 @@ public class DSL {
@NotNull
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static <T extends Number> Field<T> bitNot(Field<T> field) {
return new Neg<>(nullSafe(field), ExpressionOperator.BIT_NOT);
return new Neg<>(nullSafe(field), false, ExpressionOperator.BIT_NOT);
}
/**
@ -20104,7 +20108,10 @@ public class DSL {
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
public static Field<BigDecimal> coth(Field<? extends Number> field) {
field = nullSafe(field);
return exp(field.mul(2)).add(1).div(exp(field.mul(2)).sub(1));
return idiv(
iadd(exp(imul(field, two())), one()),
isub(exp(imul(field, two())), one())
);
}
/**
@ -26096,7 +26103,7 @@ public class DSL {
@NotNull
@Support
public static Field<BigDecimal> tau() {
return pi().times(two());
return imul(pi(), two());
}
/**

View File

@ -76,6 +76,10 @@ import static org.jooq.impl.ExpressionOperator.MULTIPLY;
import static org.jooq.impl.ExpressionOperator.SHL;
import static org.jooq.impl.ExpressionOperator.SHR;
import static org.jooq.impl.ExpressionOperator.SUBTRACT;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Keywords.K_AS;
import static org.jooq.impl.Keywords.K_CAST;
import static org.jooq.impl.Keywords.K_DAY;
@ -162,6 +166,11 @@ final class Expression<T> extends AbstractField<T> {
SQLDialect family = ctx.family();
// ---------------------------------------------------------------------
@ -209,12 +218,12 @@ final class Expression<T> extends AbstractField<T> {
// Many dialects don't support shifts. Use multiplication/division instead
else if (SHL == operator && EMULATE_SHR_SHL.contains(ctx.dialect()))
ctx.visit(lhs.mul((Field<? extends Number>) castIfNeeded(DSL.power(two(), rhsAsNumber()), lhs)));
ctx.visit(imul(lhs, (Field<? extends Number>) castIfNeeded(DSL.power(two(), rhsAsNumber()), lhs)));
// [#3962] This emulation is expensive. If this is emulated, BitCount should
// use division instead of SHR directly
else if (SHR == operator && EMULATE_SHR_SHL.contains(ctx.dialect()))
ctx.visit(lhs.div((Field<? extends Number>) castIfNeeded(DSL.power(two(), rhsAsNumber()), lhs)));
ctx.visit(idiv(lhs, (Field<? extends Number>) castIfNeeded(DSL.power(two(), rhsAsNumber()), lhs)));
// Use the default operator expression for all other cases
else
@ -247,6 +256,11 @@ final class Expression<T> extends AbstractField<T> {
// Use the default operator expression for all other cases
else
ctx.visit(new DefaultExpression<>(lhs, operator, rhs));
}
@ -331,6 +345,8 @@ final class Expression<T> extends AbstractField<T> {

View File

@ -43,6 +43,9 @@ import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.isoDayOfWeek;
import static org.jooq.impl.DSL.keyword;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Keywords.K_DATE;
import static org.jooq.impl.Keywords.K_DAY;
import static org.jooq.impl.Keywords.K_FROM;
@ -414,44 +417,55 @@ final class Extract extends AbstractField<Integer> {
}
private final static Field<Integer> dowISOToSun1(Field<Integer> dow) {
return dow.mod(inline(7)).add(one());
return iadd(dow.mod(inline(7)), one());
}
private final static Field<Integer> dowSun1ToISO(Field<Integer> dow) {
return dow.add(inline(5)).mod(inline(7)).add(one());
return iadd(iadd(dow, inline(5)).mod(inline(7)), one());
}
private final static Field<Integer> dowSun0ToISO(Field<Integer> dow) {
return dow.add(inline(6)).mod(inline(7)).add(one());
return iadd(iadd(dow, inline(6)).mod(inline(7)), one());
}
private final void acceptDefaultEmulation(Context<?> ctx) {
switch (datePart) {
case DECADE:
ctx.visit(DSL.floor(DSL.year(field).div(inline(10))));
ctx.visit(DSL.floor(idiv(DSL.year(field), inline(10))));
break;
case CENTURY:
ctx.visit(DSL.floor(
DSL.sign(DSL.year(field))
.mul(DSL.abs(DSL.year(field)).add(inline(99)))
.div(inline(100))));
ctx.visit(DSL.floor(idiv(
imul(
DSL.sign(DSL.year(field)),
iadd(DSL.abs(DSL.year(field)), inline(99))
),
inline(100)
)));
break;
case MILLENNIUM:
ctx.visit(DSL.floor(
DSL.sign(DSL.year(field))
.mul(DSL.abs(DSL.year(field)).add(inline(999)))
.div(inline(1000))));
ctx.visit(DSL.floor(idiv(
imul(
DSL.sign(DSL.year(field)),
iadd(DSL.abs(DSL.year(field)), inline(999))
),
inline(1000)
)));
break;
case QUARTER:
ctx.visit(DSL.floor(DSL.month(field).add(inline(2)).div(inline(3))));
ctx.visit(DSL.floor(idiv(
iadd(DSL.month(field), inline(2)),
inline(3)
)));
break;
case TIMEZONE:
ctx.visit(DSL.extract(field, DatePart.TIMEZONE_HOUR).mul(inline(3600))
.add(DSL.extract(field, DatePart.TIMEZONE_MINUTE).mul(inline(60))));
ctx.visit(iadd(
imul(DSL.extract(field, DatePart.TIMEZONE_HOUR), inline(3600)),
imul(DSL.extract(field, DatePart.TIMEZONE_MINUTE), inline(60))
));
break;
default:

View File

@ -43,9 +43,9 @@ import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.unquotedName;
import static org.jooq.impl.DSL.withRecursive;
import static org.jooq.impl.Internal.add;
import static org.jooq.impl.Internal.mul;
import static org.jooq.impl.Internal.sub;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Names.N_GENERATE_SERIES;
import static org.jooq.impl.Names.N_SYSTEM_RANGE;
import static org.jooq.impl.SQLDataType.INTEGER;
@ -105,7 +105,7 @@ final class GenerateSeries extends AbstractTable<Record1<Integer>> {
visitSubquery(
ctx,
withRecursive(N_GENERATE_SERIES, v)
.as(select(from).unionAll(select(f.plus(step == null ? inline(1) : step)).from(N_GENERATE_SERIES).where(f.lt(to))))
.as(select(from).unionAll(select(iadd(f, step == null ? inline(1) : step)).from(N_GENERATE_SERIES).where(f.lt(to))))
.select(f.as(N_GENERATE_SERIES)).from(N_GENERATE_SERIES),
true
);

View File

@ -364,22 +364,27 @@ public final class Internal {
}
@Support
static final <T> Field<T> add(Field<T> lhs, Field<T> rhs) {
static final <T> Field<T> ineg(Field<T> field) {
return new Neg<>(field, true, ExpressionOperator.SUBTRACT);
}
@Support
static final <T> Field<T> iadd(Field<T> lhs, Field<?> rhs) {
return new Expression<>(ADD, true, lhs, nullSafe(rhs, lhs.getDataType()));
}
@Support
static final <T> Field<T> sub(Field<T> lhs, Field<T> rhs) {
static final <T> Field<T> isub(Field<T> lhs, Field<?> rhs) {
return new Expression<>(SUBTRACT, true, lhs, nullSafe(rhs, lhs.getDataType()));
}
@Support
static final <T> Field<T> mul(Field<T> lhs, Field<T> rhs) {
static final <T> Field<T> imul(Field<T> lhs, Field<?> rhs) {
return new Expression<>(MULTIPLY, true, lhs, nullSafe(rhs, lhs.getDataType()));
}
@Support
static final <T> Field<T> div(Field<T> lhs, Field<T> rhs) {
static final <T> Field<T> idiv(Field<T> lhs, Field<?> rhs) {
return new Expression<>(DIVIDE, true, lhs, nullSafe(rhs, lhs.getDataType()));
}
}

View File

@ -45,6 +45,7 @@ import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.val;
import static org.jooq.impl.DSL.zero;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Keywords.K_FETCH_FIRST;
import static org.jooq.impl.Keywords.K_FETCH_NEXT;
import static org.jooq.impl.Keywords.K_FIRST;
@ -423,7 +424,7 @@ final class Limit extends AbstractQueryPart {
* The upper bound, such that ROW_NUMBER() &lt;= getUpperRownum()
*/
final Field<?> getUpperRownum() {
return offsetOrZero.add(numberOfRowsOrMax);
return iadd(offsetOrZero, numberOfRowsOrMax);
}
/**

View File

@ -38,6 +38,7 @@
package org.jooq.impl;
import static org.jooq.impl.DSL.function;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Names.N_LN;
import static org.jooq.impl.SQLDataType.NUMERIC;
@ -126,7 +127,7 @@ final class Ln extends AbstractField<BigDecimal> {
case DERBY:
case HSQLDB:
ctx.visit(DSL.ln(argument).div(DSL.ln(base)));
ctx.visit(idiv(DSL.ln(argument), DSL.ln(base)));
return;
default:

View File

@ -320,6 +320,8 @@ package org.jooq.impl;

View File

@ -38,6 +38,7 @@
package org.jooq.impl;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Names.N_HEX;
import static org.jooq.impl.Names.N_LEN;
import static org.jooq.impl.Names.N_LENGTH;

View File

@ -66,14 +66,16 @@ final class Neg<T> extends AbstractField<T> {
private static final Set<SQLDialect> EMULATE_BIT_NOT = SQLDialect.supportedBy(HSQLDB);
private static final Set<SQLDialect> SUPPORT_BIT_NOT = SQLDialect.supportedBy(H2);
private final ExpressionOperator operator;
private final Field<T> field;
private final boolean internal;
private final ExpressionOperator operator;
Neg(Field<T> field, ExpressionOperator operator) {
Neg(Field<T> field, boolean internal, ExpressionOperator operator) {
super(operator.toName(), field.getDataType());
this.operator = operator;
this.field = field;
this.internal = internal;
this.operator = operator;
}
@Override

View File

@ -59,6 +59,8 @@ import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Keywords.K_FOR;
import static org.jooq.impl.Keywords.K_FROM;
import static org.jooq.impl.Keywords.K_PLACING;
@ -114,9 +116,9 @@ final class Overlay extends AbstractField<String> {
}
else if (NO_SUPPORT.contains(ctx.dialect())) {
ctx.visit(
DSL.substring(in, inline(1), startIndex.minus(inline(1)))
DSL.substring(in, inline(1), isub(startIndex, inline(1)))
.concat(placing)
.concat(DSL.substring(in, startIndex.plus(l)))
.concat(DSL.substring(in, iadd(startIndex, l)))
);
}
else {
@ -132,9 +134,9 @@ final class Overlay extends AbstractField<String> {
}
else if (NO_SUPPORT.contains(ctx.dialect())) {
ctx.visit(
DSL.substring(in, inline(1), startIndex.minus(inline(1)))
DSL.substring(in, inline(1), isub(startIndex, inline(1)))
.concat(placing)
.concat(DSL.substring(in, startIndex.plus(DSL.length(placing))))
.concat(DSL.substring(in, iadd(startIndex, DSL.length(placing))))
);
}
else {

View File

@ -41,6 +41,7 @@ import static org.jooq.impl.DSL.function;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.two;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Names.N_PI;
import java.math.BigDecimal;

View File

@ -39,6 +39,8 @@
package org.jooq.impl;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Keywords.K_IN;
import static org.jooq.impl.Names.N_CHARINDEX;
import static org.jooq.impl.Names.N_INSTR;
@ -89,7 +91,7 @@ final class Position extends AbstractField<Integer> {
default:
ctx.visit(DSL.position(DSL.substring(in, startIndex), search).add(startIndex).sub(one()));
ctx.visit(iadd(DSL.position(DSL.substring(in, startIndex), search), isub(startIndex, one())));
break;
}
else

View File

@ -37,6 +37,7 @@
*/
package org.jooq.impl;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Names.N_POWER;
import static org.jooq.impl.SQLDataType.NUMERIC;
@ -76,7 +77,7 @@ final class Power extends AbstractField<BigDecimal> {
case DERBY:
case SQLITE:
ctx.visit(DSL.exp(DSL.ln(arg1).mul(arg2)));
ctx.visit(DSL.exp(imul(DSL.ln(arg1), arg2)));
break;
default:

View File

@ -43,6 +43,7 @@ import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.when;
import static org.jooq.impl.DSL.zero;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Names.N_PRODUCT;
import static org.jooq.impl.SQLDataType.NUMERIC;
@ -118,10 +119,11 @@ final class Product extends AbstractAggregateFunction<BigDecimal> {
}
};
ctx.visit(
when(zerosSum.gt(inline(BigDecimal.ZERO)), zero())
.when(negativesSum.mod(inline(2)).lt(inline(BigDecimal.ZERO)), inline(-1))
.otherwise(one()).mul(DSL.exp(logarithmsSum))
);
ctx.visit(imul(
when(zerosSum.gt(inline(BigDecimal.ZERO)), zero())
.when(negativesSum.mod(inline(2)).lt(inline(BigDecimal.ZERO)), inline(-1))
.otherwise(one()),
DSL.exp(logarithmsSum)
));
}
}

View File

@ -42,6 +42,8 @@ package org.jooq.impl;
import static org.jooq.impl.DSL.case_;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.rank;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.RankingFunction.RankingType.CUME_DIST;
import static org.jooq.impl.RankingFunction.RankingType.PERCENT_RANK;
import static org.jooq.impl.SQLDataType.NUMERIC;
@ -100,6 +102,9 @@ final class RankingFunction<T> extends AbstractWindowFunction<T> implements Orde
{
ctx.visit(rankingType.name).sql("()");

View File

@ -37,6 +37,7 @@
*/
package org.jooq.impl;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Names.N_HEX;
import static org.jooq.impl.Names.N_REPEAT;
import static org.jooq.impl.Names.N_REPLACE;
@ -79,7 +80,7 @@ final class Repeat extends AbstractField<String> {
case FIREBIRD:
ctx.visit(DSL.rpad(string, DSL.length(string).mul(count), string));
ctx.visit(DSL.rpad(string, imul(DSL.length(string), count), string));
break;
// Emulation of REPEAT() for SQLite currently cannot be achieved

View File

@ -38,6 +38,8 @@
package org.jooq.impl;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Names.N_RIGHT;
import org.jooq.Context;
@ -67,7 +69,7 @@ final class Right extends AbstractField<String> {
public final void accept(Context<?> ctx) {
switch (ctx.family()) {
case DERBY:
ctx.visit(DSL.substring(field, field.length().add(one()).sub(length)));
ctx.visit(DSL.substring(field, iadd(DSL.length(field), isub(one(), length))));
break;

View File

@ -39,6 +39,9 @@ package org.jooq.impl;
import static org.jooq.impl.DSL.function;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Names.N_ROUND;
import static org.jooq.impl.SQLDataType.NUMERIC;
import static org.jooq.impl.Tools.castIfNeeded;
@ -82,7 +85,7 @@ final class Round<T extends Number> extends AbstractField<T> {
case DERBY: {
if (decimals == null) {
ctx.visit(DSL
.when(argument.sub(DSL.floor(argument))
.when(isub(argument, DSL.floor(argument))
.lessThan((T) Double.valueOf(0.5)), DSL.floor(argument))
.otherwise(DSL.ceil(argument)));
@ -91,12 +94,12 @@ final class Round<T extends Number> extends AbstractField<T> {
else if (decimals instanceof Param) {
Integer decimalsValue = ((Param<Integer>) decimals).getValue();
Field<BigDecimal> factor = DSL.val(BigDecimal.ONE.movePointRight(decimalsValue));
Field<T> mul = argument.mul(factor);
Field<T> mul = imul(argument, factor);
ctx.visit(DSL
.when(mul.sub(DSL.floor(mul))
.lessThan((T) Double.valueOf(0.5)), DSL.floor(mul).div(factor))
.otherwise(DSL.ceil(mul).div(factor)));
.when(isub(mul, DSL.floor(mul))
.lessThan((T) Double.valueOf(0.5)), idiv(DSL.floor(mul), factor))
.otherwise(idiv(DSL.ceil(mul), factor)));
return;
}

View File

@ -60,6 +60,7 @@ import static org.jooq.SQLDialect.MYSQL;
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Keywords.K_OVERLAPS;
import static org.jooq.impl.Tools.castIfNeeded;
@ -114,7 +115,7 @@ final class RowOverlapsCondition<T1, T2> extends AbstractCondition {
// Interval OVERLAPS predicates need some additional arithmetic
if (intervalOverlaps)
ctx.visit(right1.le(left1.add(left2)).and(left1.le(right1.add(right2))));
ctx.visit(right1.le(iadd(left1, left2)).and(left1.le(iadd(right1, right2))));
// All other OVERLAPS predicates can be emulated simply
else
@ -123,7 +124,7 @@ final class RowOverlapsCondition<T1, T2> extends AbstractCondition {
// These dialects seem to have trouble with INTERVAL OVERLAPS predicates
else if (intervalOverlaps && EMULATE_INTERVAL_OVERLAPS.contains(ctx.dialect()))
ctx.visit(right1.le(left1.add(left2)).and(left1.le(right1.add(right2))));
ctx.visit(right1.le(iadd(left1, left2)).and(left1.le(iadd(right1, right2))));
// Everyone else can handle OVERLAPS
else

View File

@ -38,6 +38,7 @@
package org.jooq.impl;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Names.N_HEX;
import static org.jooq.impl.Names.N_LEN;
import static org.jooq.impl.Names.N_LENGTH;

View File

@ -39,6 +39,9 @@ package org.jooq.impl;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.two;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Names.N_SINH;
import static org.jooq.impl.SQLDataType.NUMERIC;
@ -87,7 +90,10 @@ final class Sinh extends AbstractField<BigDecimal> {
case MARIADB:
case MYSQL:
case POSTGRES:
ctx.visit(DSL.exp(argument.mul(two())).sub(one()).div(DSL.exp(argument).mul(two())));
ctx.visit(idiv(
isub(DSL.exp(imul(argument, two())), one()),
imul(DSL.exp(argument), two())
));
break;
default:

View File

@ -39,6 +39,10 @@ package org.jooq.impl;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.two;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Names.N_TANH;
import static org.jooq.impl.SQLDataType.NUMERIC;
@ -87,7 +91,10 @@ final class Tanh extends AbstractField<BigDecimal> {
case MARIADB:
case MYSQL:
case POSTGRES:
ctx.visit(DSL.exp(argument.mul(two())).sub(one()).div(DSL.exp(argument.mul(two())).add(one())));
ctx.visit(idiv(
isub(DSL.exp(imul(argument, two())), one()),
iadd(DSL.exp(imul(argument, two())), one())
));
break;
default:

View File

@ -40,6 +40,8 @@ package org.jooq.impl;
import static java.math.BigDecimal.TEN;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.zero;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Names.N_ROUND;
import static org.jooq.impl.Names.N_ROUND_DOWN;
import static org.jooq.impl.Names.N_TRUNC;
@ -95,10 +97,8 @@ final class Trunc<T> extends AbstractField<T> {
}
ctx.visit(DSL.decode()
.when(field.sign().greaterOrEqual(zero()),
field.mul(power).floor().div(power))
.otherwise(
field.mul(power).ceil().div(power)));
.when(field.sign().greaterOrEqual(zero()), idiv(imul(field, power).floor(), power))
.otherwise(idiv(imul(field, power).ceil(), power)));
break;
}

View File

@ -40,6 +40,10 @@ package org.jooq.impl;
import static org.jooq.impl.DSL.keyword;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.zero;
import static org.jooq.impl.Internal.iadd;
import static org.jooq.impl.Internal.idiv;
import static org.jooq.impl.Internal.imul;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.Names.N_WIDTH_BUCKET;
import org.jooq.Context;
@ -88,8 +92,14 @@ final class WidthBucket<T extends Number> extends AbstractField<T> {
default:
ctx.visit(
DSL.when(field.lt(low), zero())
.when(field.ge(high), buckets.add(one()))
.otherwise((Field<Integer>) DSL.floor(field.sub(low).mul(buckets).div(high.sub(low))).add(one()))
.when(field.ge(high), iadd(buckets, one()))
.otherwise((Field<Integer>) iadd(
DSL.floor(idiv(
imul(isub(field, low), buckets),
isub(high, low)
)),
one()
))
);
break;
}