diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java
index d4d66fbf7f..8cff54b40b 100644
--- a/jOOQ/src/main/java/org/jooq/conf/Settings.java
+++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java
@@ -94,6 +94,9 @@ public class Settings
protected Boolean transformAnsiJoinToTableLists = false;
@XmlElement(defaultValue = "false")
protected Boolean transformTableListsToAnsiJoin = false;
+ @XmlElement(defaultValue = "NEVER")
+ @XmlSchemaType(name = "string")
+ protected TransformUnneededArithmeticExpressions transformUnneededArithmeticExpressions = TransformUnneededArithmeticExpressions.NEVER;
@XmlElement(defaultValue = "DEFAULT")
@XmlSchemaType(name = "string")
protected BackslashEscaping backslashEscaping = BackslashEscaping.DEFAULT;
@@ -778,7 +781,7 @@ public class Settings
}
/**
- * Transform ANSI join to table lists if possible
+ * Transform ANSI join to table lists if possible.
*
* Historically, prior to ANSI join syntax, joins were implemented by listing tables in
* the FROM clause and providing join predicates in the WHERE clause, possibly using vendor specific
@@ -813,7 +816,7 @@ public class Settings
}
/**
- * Transform table lists to ANSI join if possible
+ * Transform table lists to ANSI join if possible.
*
* (Very) historically, prior to ANSI join syntax, joins were implemented by listing tables in
* the FROM clause and providing join predicates in the WHERE clause, possibly using vendor specific
@@ -821,8 +824,6 @@ public class Settings
* support. Migrating such join syntax is tedious. The jOOQ parser can parse the old syntax and
* this flag enables the transformation to ANSI join syntax.
*
- * This flag has not been implemented yet!
- *
* This feature is available in the commercial distribution only.
*
* @return
@@ -846,6 +847,32 @@ public class Settings
this.transformTableListsToAnsiJoin = value;
}
+ /**
+ * Transform arithmetic expressions on literals and bind variables.
+ *
+ * Arithmetic expressions may be implemented by the user, or arise from emulations from within jOOQ.
+ * Expressions on literals and bind variables could be evaluated in the client prior to generating SQL.
+ *
+ * This feature is available in the commercial distribution only.
+ *
+ */
+ public TransformUnneededArithmeticExpressions getTransformUnneededArithmeticExpressions() {
+ return transformUnneededArithmeticExpressions;
+ }
+
+ /**
+ * Transform arithmetic expressions on literals and bind variables.
+ *
+ * Arithmetic expressions may be implemented by the user, or arise from emulations from within jOOQ.
+ * Expressions on literals and bind variables could be evaluated in the client prior to generating SQL.
+ *
+ * This feature is available in the commercial distribution only.
+ *
+ */
+ public void setTransformUnneededArithmeticExpressions(TransformUnneededArithmeticExpressions value) {
+ this.transformUnneededArithmeticExpressions = value;
+ }
+
/**
* Whether string literals should be escaped with backslash.
*
@@ -2405,6 +2432,20 @@ public class Settings
return this;
}
+ /**
+ * Transform arithmetic expressions on literals and bind variables.
+ *
+ * Arithmetic expressions may be implemented by the user, or arise from emulations from within jOOQ.
+ * Expressions on literals and bind variables could be evaluated in the client prior to generating SQL.
+ *
+ * This feature is available in the commercial distribution only.
+ *
+ */
+ public Settings withTransformUnneededArithmeticExpressions(TransformUnneededArithmeticExpressions value) {
+ setTransformUnneededArithmeticExpressions(value);
+ return this;
+ }
+
/**
* Whether string literals should be escaped with backslash.
*
@@ -2977,6 +3018,7 @@ public class Settings
builder.append("fetchTriggerValuesAfterSQLServerOutput", fetchTriggerValuesAfterSQLServerOutput);
builder.append("transformAnsiJoinToTableLists", transformAnsiJoinToTableLists);
builder.append("transformTableListsToAnsiJoin", transformTableListsToAnsiJoin);
+ builder.append("transformUnneededArithmeticExpressions", transformUnneededArithmeticExpressions);
builder.append("backslashEscaping", backslashEscaping);
builder.append("paramType", paramType);
builder.append("paramCastMode", paramCastMode);
@@ -3282,6 +3324,15 @@ public class Settings
return false;
}
}
+ if (transformUnneededArithmeticExpressions == null) {
+ if (other.transformUnneededArithmeticExpressions!= null) {
+ return false;
+ }
+ } else {
+ if (!transformUnneededArithmeticExpressions.equals(other.transformUnneededArithmeticExpressions)) {
+ return false;
+ }
+ }
if (backslashEscaping == null) {
if (other.backslashEscaping!= null) {
return false;
@@ -3925,6 +3976,7 @@ public class Settings
result = ((prime*result)+((fetchTriggerValuesAfterSQLServerOutput == null)? 0 :fetchTriggerValuesAfterSQLServerOutput.hashCode()));
result = ((prime*result)+((transformAnsiJoinToTableLists == null)? 0 :transformAnsiJoinToTableLists.hashCode()));
result = ((prime*result)+((transformTableListsToAnsiJoin == null)? 0 :transformTableListsToAnsiJoin.hashCode()));
+ result = ((prime*result)+((transformUnneededArithmeticExpressions == null)? 0 :transformUnneededArithmeticExpressions.hashCode()));
result = ((prime*result)+((backslashEscaping == null)? 0 :backslashEscaping.hashCode()));
result = ((prime*result)+((paramType == null)? 0 :paramType.hashCode()));
result = ((prime*result)+((paramCastMode == null)? 0 :paramCastMode.hashCode()));
diff --git a/jOOQ/src/main/java/org/jooq/conf/SettingsTools.java b/jOOQ/src/main/java/org/jooq/conf/SettingsTools.java
index ab05600b39..6da319ed4e 100644
--- a/jOOQ/src/main/java/org/jooq/conf/SettingsTools.java
+++ b/jOOQ/src/main/java/org/jooq/conf/SettingsTools.java
@@ -296,6 +296,15 @@ public final class SettingsTools {
return result == null ? ExecuteWithoutWhere.LOG_DEBUG : result;
}
+ /**
+ * Lazy access to {@link Settings#getTransformUnneededArithmeticExpressions()}.
+ */
+ public static final TransformUnneededArithmeticExpressions getTransformUnneededArithmeticExpressions(Settings settings) {
+ return settings.getTransformUnneededArithmeticExpressions() != null
+ ? settings.getTransformUnneededArithmeticExpressions()
+ : TransformUnneededArithmeticExpressions.NEVER;
+ }
+
/**
* Retrieve the configured default settings.
*
diff --git a/jOOQ/src/main/java/org/jooq/conf/TransformUnneededArithmeticExpressions.java b/jOOQ/src/main/java/org/jooq/conf/TransformUnneededArithmeticExpressions.java
new file mode 100644
index 0000000000..d85b86e0ce
--- /dev/null
+++ b/jOOQ/src/main/java/org/jooq/conf/TransformUnneededArithmeticExpressions.java
@@ -0,0 +1,40 @@
+
+package org.jooq.conf;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ *
Java class for TransformUnneededArithmeticExpressions.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
+ * <simpleType name="TransformUnneededArithmeticExpressions">
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ * <enumeration value="NEVER"/>
+ * <enumeration value="INTERNAL"/>
+ * <enumeration value="ALWAYS"/>
+ * </restriction>
+ * </simpleType>
+ *
+ *
+ */
+@XmlType(name = "TransformUnneededArithmeticExpressions")
+@XmlEnum
+public enum TransformUnneededArithmeticExpressions {
+
+ NEVER,
+ INTERNAL,
+ ALWAYS;
+
+ public String value() {
+ return name();
+ }
+
+ public static TransformUnneededArithmeticExpressions fromValue(String v) {
+ return valueOf(v);
+ }
+
+}
diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java
index 91069b1b36..44f98eca36 100644
--- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java
+++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java
@@ -353,7 +353,7 @@ abstract class AbstractField extends AbstractTypedNamed implements Field add(Field> value) {
- return new Expression<>(ADD, this, nullSafe(value, getDataType()));
+ return new Expression<>(ADD, false, this, nullSafe(value, getDataType()));
}
@Override
@@ -363,7 +363,7 @@ abstract class AbstractField extends AbstractTypedNamed implements Field sub(Field> value) {
- return new Expression<>(SUBTRACT, this, nullSafe(value, getDataType()));
+ return new Expression<>(SUBTRACT, false, this, nullSafe(value, getDataType()));
}
@Override
@@ -377,7 +377,7 @@ abstract class AbstractField extends AbstractTypedNamed implements Field mul(Field extends Number> value) {
- return new Expression<>(MULTIPLY, this, nullSafe(value, getDataType()));
+ return new Expression<>(MULTIPLY, false, this, nullSafe(value, getDataType()));
}
@Override
@@ -387,7 +387,7 @@ abstract class AbstractField extends AbstractTypedNamed implements Field div(Field extends Number> value) {
- return new Expression<>(DIVIDE, this, nullSafe(value, getDataType()));
+ return new Expression<>(DIVIDE, false, this, nullSafe(value, getDataType()));
}
@Override
diff --git a/jOOQ/src/main/java/org/jooq/impl/Concat.java b/jOOQ/src/main/java/org/jooq/impl/Concat.java
index e91bca39c1..b2704d5ff7 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Concat.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Concat.java
@@ -106,7 +106,7 @@ final class Concat extends AbstractField {
default:
- ctx.visit(new Expression<>(CONCAT, first, others));
+ ctx.visit(new Expression<>(CONCAT, false, first, others));
break;
}
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java
index 8da1b690e7..26c5d3902f 100644
--- a/jOOQ/src/main/java/org/jooq/impl/DSL.java
+++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java
@@ -18906,7 +18906,7 @@ public class DSL {
@NotNull
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static Field bitAnd(Field field1, Field field2) {
- return new Expression<>(ExpressionOperator.BIT_AND, nullSafe(field1), nullSafe(field2));
+ return new Expression<>(ExpressionOperator.BIT_AND, false, nullSafe(field1), nullSafe(field2));
}
/**
@@ -18960,7 +18960,7 @@ public class DSL {
@NotNull
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static Field bitNand(Field field1, Field field2) {
- return new Expression<>(ExpressionOperator.BIT_NAND, nullSafe(field1), nullSafe(field2));
+ return new Expression<>(ExpressionOperator.BIT_NAND, false, nullSafe(field1), nullSafe(field2));
}
/**
@@ -19009,7 +19009,7 @@ public class DSL {
@NotNull
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static Field bitOr(Field field1, Field field2) {
- return new Expression<>(ExpressionOperator.BIT_OR, nullSafe(field1), nullSafe(field2));
+ return new Expression<>(ExpressionOperator.BIT_OR, false, nullSafe(field1), nullSafe(field2));
}
/**
@@ -19061,7 +19061,7 @@ public class DSL {
@NotNull
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static Field bitNor(Field field1, Field field2) {
- return new Expression<>(ExpressionOperator.BIT_NOR, nullSafe(field1), nullSafe(field2));
+ return new Expression<>(ExpressionOperator.BIT_NOR, false, nullSafe(field1), nullSafe(field2));
}
/**
@@ -19110,7 +19110,7 @@ public class DSL {
@NotNull
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static Field bitXor(Field field1, Field field2) {
- return new Expression<>(ExpressionOperator.BIT_XOR, nullSafe(field1), nullSafe(field2));
+ return new Expression<>(ExpressionOperator.BIT_XOR, false, nullSafe(field1), nullSafe(field2));
}
/**
@@ -19162,7 +19162,7 @@ public class DSL {
@NotNull
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static Field bitXNor(Field field1, Field field2) {
- return new Expression<>(ExpressionOperator.BIT_XNOR, nullSafe(field1), nullSafe(field2));
+ return new Expression<>(ExpressionOperator.BIT_XNOR, false, nullSafe(field1), nullSafe(field2));
}
/**
@@ -19213,7 +19213,7 @@ public class DSL {
@NotNull
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static Field shl(Field field1, Field extends Number> field2) {
- return new Expression<>(ExpressionOperator.SHL, nullSafe(field1), nullSafe(field2));
+ return new Expression<>(ExpressionOperator.SHL, false, nullSafe(field1), nullSafe(field2));
}
/**
@@ -19264,7 +19264,7 @@ public class DSL {
@NotNull
@Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
public static Field shr(Field field1, Field extends Number> field2) {
- return new Expression<>(ExpressionOperator.SHR, nullSafe(field1), nullSafe(field2));
+ return new Expression<>(ExpressionOperator.SHR, false, nullSafe(field1), nullSafe(field2));
}
// ------------------------------------------------------------------------
diff --git a/jOOQ/src/main/java/org/jooq/impl/Expression.java b/jOOQ/src/main/java/org/jooq/impl/Expression.java
index d4da86bfb0..3f89a15115 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Expression.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Expression.java
@@ -59,6 +59,7 @@ import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
// ...
+import static org.jooq.conf.SettingsTools.getTransformUnneededArithmeticExpressions;
import static org.jooq.impl.DSL.function;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.keyword;
@@ -98,6 +99,7 @@ import static org.jooq.impl.Names.N_SQL_TSI_SECOND;
import static org.jooq.impl.Names.N_STRFTIME;
import static org.jooq.impl.Names.N_TIMESTAMPADD;
import static org.jooq.impl.QueryPartListView.wrap;
+import static org.jooq.impl.Tools.EMPTY_FIELD;
import static org.jooq.impl.Tools.castIfNeeded;
import java.sql.Timestamp;
@@ -109,8 +111,11 @@ import org.jooq.DataType;
import org.jooq.DatePart;
import org.jooq.Field;
import org.jooq.Param;
+// ...
import org.jooq.SQLDialect;
+import org.jooq.conf.TransformUnneededArithmeticExpressions;
import org.jooq.exception.DataTypeException;
+import org.jooq.impl.Tools.DataExtendedKey;
import org.jooq.types.DayToSecond;
import org.jooq.types.Interval;
import org.jooq.types.YearToMonth;
@@ -129,15 +134,17 @@ final class Expression extends AbstractField {
private static final Set HASH_OP_FOR_BIT_XOR = SQLDialect.supportedBy(POSTGRES);
private static final Set SUPPORT_YEAR_TO_SECOND = SQLDialect.supportedBy(POSTGRES);
+ private final ExpressionOperator operator;
+ private final boolean internal;
private final Field lhs;
private final QueryPartList> rhs;
private final Field>[] arguments;
- private final ExpressionOperator operator;
- Expression(ExpressionOperator operator, Field lhs, Field>... rhs) {
+ Expression(ExpressionOperator operator, boolean internal, Field lhs, Field>... rhs) {
super(DSL.name(operator.toSQL()), lhs.getDataType());
this.operator = operator;
+ this.internal = internal;
this.lhs = lhs;
this.rhs = new QueryPartList<>(rhs);
this.arguments = Tools.combine(lhs, rhs);
@@ -166,6 +173,17 @@ final class Expression extends AbstractField {
@SuppressWarnings("unchecked")
@Override
public final void accept(Context> ctx) {
+
+
+
+
+
+
+
+
+
+
+
SQLDialect family = ctx.family();
// ---------------------------------------------------------------------
@@ -253,6 +271,36 @@ final class Expression extends AbstractField {
ctx.visit(new DefaultExpression<>(lhs, operator, rhs));
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/**
* In some expressions, the lhs can be safely assumed to be a single number
*/
diff --git a/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java b/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java
index 39364e7302..0b4fbcf6a9 100644
--- a/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java
+++ b/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java
@@ -43,6 +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.Names.N_GENERATE_SERIES;
import static org.jooq.impl.Names.N_SYSTEM_RANGE;
import static org.jooq.impl.SQLDataType.INTEGER;
diff --git a/jOOQ/src/main/java/org/jooq/impl/Internal.java b/jOOQ/src/main/java/org/jooq/impl/Internal.java
index 1b0f1f31ec..302a411aab 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Internal.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Internal.java
@@ -37,12 +37,16 @@
*/
package org.jooq.impl;
+import static org.jooq.impl.DSL.nullSafe;
+import static org.jooq.impl.ExpressionOperator.*;
+
import org.jooq.Binding;
import org.jooq.Check;
import org.jooq.Converter;
import org.jooq.DataType;
import org.jooq.Domain;
import org.jooq.EmbeddableRecord;
+import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Identity;
import org.jooq.Index;
@@ -53,6 +57,7 @@ import org.jooq.Parameter;
import org.jooq.Record;
import org.jooq.Schema;
import org.jooq.Sequence;
+import org.jooq.Support;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.UDT;
@@ -357,4 +362,24 @@ public final class Internal {
public static final > TableField[] fields(TableField embeddableField) {
return ((EmbeddableTableField) embeddableField).fields;
}
+
+ @Support
+ static final Field add(Field lhs, Field rhs) {
+ return new Expression<>(ADD, true, lhs, nullSafe(rhs, lhs.getDataType()));
+ }
+
+ @Support
+ static final Field sub(Field lhs, Field rhs) {
+ return new Expression<>(SUBTRACT, true, lhs, nullSafe(rhs, lhs.getDataType()));
+ }
+
+ @Support
+ static final Field mul(Field lhs, Field rhs) {
+ return new Expression<>(MULTIPLY, true, lhs, nullSafe(rhs, lhs.getDataType()));
+ }
+
+ @Support
+ static final Field div(Field lhs, Field rhs) {
+ return new Expression<>(DIVIDE, true, lhs, nullSafe(rhs, lhs.getDataType()));
+ }
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/Mod.java b/jOOQ/src/main/java/org/jooq/impl/Mod.java
index d7222f33d7..9ec8c994e1 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Mod.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Mod.java
@@ -79,7 +79,7 @@ final class Mod extends AbstractField {
case SQLITE:
- ctx.visit(new Expression<>(MODULO, arg1, arg2));
+ ctx.visit(new Expression<>(MODULO, false, arg1, arg2));
break;
default:
ctx.visit(K_MOD).sql('(').visit(arg1).sql(", ").visit(arg2).sql(')');
diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java
index 87e26ba4a9..8e718ec23d 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Tools.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java
@@ -654,6 +654,12 @@ final class Tools {
+
+
+
+
+
+
diff --git a/jOOQ/src/main/resources/xsd/jooq-runtime-3.14.0.xsd b/jOOQ/src/main/resources/xsd/jooq-runtime-3.14.0.xsd
index f6bdcbe795..1ddb7e8bd3 100644
--- a/jOOQ/src/main/resources/xsd/jooq-runtime-3.14.0.xsd
+++ b/jOOQ/src/main/resources/xsd/jooq-runtime-3.14.0.xsd
@@ -190,7 +190,7 @@ For details, see https://gith
-
Historically, prior to ANSI join syntax, joins were implemented by listing tables in
the FROM clause and providing join predicates in the WHERE clause, possibly using vendor specific
@@ -205,7 +205,7 @@ This feature is available in the commercial distribution only.]]><
-
(Very) historically, prior to ANSI join syntax, joins were implemented by listing tables in
the FROM clause and providing join predicates in the WHERE clause, possibly using vendor specific
@@ -213,7 +213,14 @@ operators like (+) (Oracle, DB2) or *= (SQL Server) fo
support. Migrating such join syntax is tedious. The jOOQ parser can parse the old syntax and
this flag enables the transformation to ANSI join syntax.
-This flag has not been implemented yet!
+This feature is available in the commercial distribution only.]]>
+
+
+
+
+Arithmetic expressions may be implemented by the user, or arise from emulations from within jOOQ.
+Expressions on literals and bind variables could be evaluated in the client prior to generating SQL.
This feature is available in the commercial distribution only.]]>
@@ -1091,4 +1098,18 @@ Either <input/> or <inputExpression/> must be provided]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file