diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java index f9641d834f..920dd2ad87 100644 --- a/jOOQ/src/main/java/org/jooq/conf/Settings.java +++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java @@ -112,6 +112,16 @@ public class Settings @XmlSchemaType(name = "string") protected FetchIntermediateResult fetchIntermediateResult = FetchIntermediateResult.WHEN_RESULT_REQUESTED; @XmlElement(defaultValue = "false") + protected Boolean transformPatterns = false; + @XmlElement(defaultValue = "true") + protected Boolean transformPatternsTrim = true; + @XmlElement(defaultValue = "true") + protected Boolean transformPatternsNotNot = true; + @XmlElement(defaultValue = "true") + protected Boolean transformPatternsNegNeg = true; + @XmlElement(defaultValue = "true") + protected Boolean transformPatternsBitNotBitNot = true; + @XmlElement(defaultValue = "false") protected Boolean transformAnsiJoinToTableLists = false; @XmlElement(defaultValue = "WHEN_NEEDED") @XmlSchemaType(name = "string") @@ -1107,6 +1117,165 @@ public class Settings this.fetchIntermediateResult = value; } + /** + * Transform various syntax patterns to better versions, if possible. + *

+ * This flag enables the pattern transformation feature, which consists of several sub-flags that are + * all prefixed with "transformPatterns", e.g. {@link #transformPatternsTrim}. While the sub-flags default + * to being enabled, and can be disabled on an individual basis, the global feature itself is disabled by + * default. + *

+ * This feature is available in the commercial distribution only. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isTransformPatterns() { + return transformPatterns; + } + + /** + * Sets the value of the transformPatterns property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setTransformPatterns(Boolean value) { + this.transformPatterns = value; + } + + /** + * Transform LTRIM(RTRIM(x)) or RTRIM(LTRIM(x)) to TRIM(x) + *

+ * Historically, a few dialects did not implement TRIM(x) or TRIM(BOTH FROM x), + * so users worked around this by wrapping LTRIM() and RTRIM() with each other. + * Maintaining this is usually undesirable, so this transformation helps remove the unwanted wrapping. + *

+ * To enable this feature, {@link #transformPatterns} must be enabled as well. + *

+ * This feature is available in the commercial distribution only. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isTransformPatternsTrim() { + return transformPatternsTrim; + } + + /** + * Sets the value of the transformPatternsTrim property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setTransformPatternsTrim(Boolean value) { + this.transformPatternsTrim = value; + } + + /** + * Transform NOT(NOT(x)) to x + *

+ * For various reasons, there may be a redundant nesting of NOT unary operators, e.g. as a + * left over of some prior transformation, including manual ones. This transformation will simplify such + * redundant negations by removing them. + *

+ * To enable this feature, {@link #transformPatterns} must be enabled as well. + *

+ * This feature is available in the commercial distribution only. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isTransformPatternsNotNot() { + return transformPatternsNotNot; + } + + /** + * Sets the value of the transformPatternsNotNot property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setTransformPatternsNotNot(Boolean value) { + this.transformPatternsNotNot = value; + } + + /** + * Transform -(-(x)) to x + *

+ * For various reasons, there may be a redundant nesting of - unary operators, e.g. as a + * left over of some prior transformation, including manual ones. This transformation will simplify such + * redundant negations by removing them. + *

+ * To enable this feature, {@link #transformPatterns} must be enabled as well. + *

+ * This feature is available in the commercial distribution only. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isTransformPatternsNegNeg() { + return transformPatternsNegNeg; + } + + /** + * Sets the value of the transformPatternsNegNeg property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setTransformPatternsNegNeg(Boolean value) { + this.transformPatternsNegNeg = value; + } + + /** + * Transform ~(~(x)) to x + *

+ * For various reasons, there may be a redundant nesting of ~ unary operators, e.g. as a + * left over of some prior transformation, including manual ones. This transformation will simplify such + * redundant negations by removing them. + *

+ * To enable this feature, {@link #transformPatterns} must be enabled as well. + *

+ * This feature is available in the commercial distribution only. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isTransformPatternsBitNotBitNot() { + return transformPatternsBitNotBitNot; + } + + /** + * Sets the value of the transformPatternsBitNotBitNot property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setTransformPatternsBitNotBitNot(Boolean value) { + this.transformPatternsBitNotBitNot = value; + } + /** * Transform ANSI join to table lists if possible. *

@@ -3343,6 +3512,31 @@ public class Settings return this; } + public Settings withTransformPatterns(Boolean value) { + setTransformPatterns(value); + return this; + } + + public Settings withTransformPatternsTrim(Boolean value) { + setTransformPatternsTrim(value); + return this; + } + + public Settings withTransformPatternsNotNot(Boolean value) { + setTransformPatternsNotNot(value); + return this; + } + + public Settings withTransformPatternsNegNeg(Boolean value) { + setTransformPatternsNegNeg(value); + return this; + } + + public Settings withTransformPatternsBitNotBitNot(Boolean value) { + setTransformPatternsBitNotBitNot(value); + return this; + } + public Settings withTransformAnsiJoinToTableLists(Boolean value) { setTransformAnsiJoinToTableLists(value); return this; @@ -4166,6 +4360,11 @@ public class Settings builder.append("bindOffsetTimeType", bindOffsetTimeType); builder.append("fetchTriggerValuesAfterSQLServerOutput", fetchTriggerValuesAfterSQLServerOutput); builder.append("fetchIntermediateResult", fetchIntermediateResult); + builder.append("transformPatterns", transformPatterns); + builder.append("transformPatternsTrim", transformPatternsTrim); + builder.append("transformPatternsNotNot", transformPatternsNotNot); + builder.append("transformPatternsNegNeg", transformPatternsNegNeg); + builder.append("transformPatternsBitNotBitNot", transformPatternsBitNotBitNot); builder.append("transformAnsiJoinToTableLists", transformAnsiJoinToTableLists); builder.append("transformInConditionSubqueryWithLimitToDerivedTable", transformInConditionSubqueryWithLimitToDerivedTable); builder.append("transformQualify", transformQualify); @@ -4561,6 +4760,51 @@ public class Settings return false; } } + if (transformPatterns == null) { + if (other.transformPatterns!= null) { + return false; + } + } else { + if (!transformPatterns.equals(other.transformPatterns)) { + return false; + } + } + if (transformPatternsTrim == null) { + if (other.transformPatternsTrim!= null) { + return false; + } + } else { + if (!transformPatternsTrim.equals(other.transformPatternsTrim)) { + return false; + } + } + if (transformPatternsNotNot == null) { + if (other.transformPatternsNotNot!= null) { + return false; + } + } else { + if (!transformPatternsNotNot.equals(other.transformPatternsNotNot)) { + return false; + } + } + if (transformPatternsNegNeg == null) { + if (other.transformPatternsNegNeg!= null) { + return false; + } + } else { + if (!transformPatternsNegNeg.equals(other.transformPatternsNegNeg)) { + return false; + } + } + if (transformPatternsBitNotBitNot == null) { + if (other.transformPatternsBitNotBitNot!= null) { + return false; + } + } else { + if (!transformPatternsBitNotBitNot.equals(other.transformPatternsBitNotBitNot)) { + return false; + } + } if (transformAnsiJoinToTableLists == null) { if (other.transformAnsiJoinToTableLists!= null) { return false; @@ -5454,6 +5698,11 @@ public class Settings result = ((prime*result)+((bindOffsetTimeType == null)? 0 :bindOffsetTimeType.hashCode())); result = ((prime*result)+((fetchTriggerValuesAfterSQLServerOutput == null)? 0 :fetchTriggerValuesAfterSQLServerOutput.hashCode())); result = ((prime*result)+((fetchIntermediateResult == null)? 0 :fetchIntermediateResult.hashCode())); + result = ((prime*result)+((transformPatterns == null)? 0 :transformPatterns.hashCode())); + result = ((prime*result)+((transformPatternsTrim == null)? 0 :transformPatternsTrim.hashCode())); + result = ((prime*result)+((transformPatternsNotNot == null)? 0 :transformPatternsNotNot.hashCode())); + result = ((prime*result)+((transformPatternsNegNeg == null)? 0 :transformPatternsNegNeg.hashCode())); + result = ((prime*result)+((transformPatternsBitNotBitNot == null)? 0 :transformPatternsBitNotBitNot.hashCode())); result = ((prime*result)+((transformAnsiJoinToTableLists == null)? 0 :transformAnsiJoinToTableLists.hashCode())); result = ((prime*result)+((transformInConditionSubqueryWithLimitToDerivedTable == null)? 0 :transformInConditionSubqueryWithLimitToDerivedTable.hashCode())); result = ((prime*result)+((transformQualify == null)? 0 :transformQualify.hashCode())); diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java index 683f5d4a2f..39494ac294 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java @@ -42,6 +42,7 @@ import static java.lang.Boolean.TRUE; import static org.jooq.SQLDialect.SQLITE; import static org.jooq.conf.ParamType.INLINED; import static org.jooq.conf.SettingsTools.renderLocale; +import static org.jooq.impl.DSL.trim; import static org.jooq.impl.Identifiers.QUOTES; import static org.jooq.impl.Identifiers.QUOTE_END_DELIMITER; import static org.jooq.impl.Identifiers.QUOTE_END_DELIMITER_ESCAPED; @@ -64,12 +65,13 @@ import org.jooq.Configuration; import org.jooq.Constants; import org.jooq.Field; import org.jooq.ForeignKey; -import org.jooq.LanguageContext; import org.jooq.Param; +// ... import org.jooq.Query; import org.jooq.QueryPart; import org.jooq.QueryPartInternal; import org.jooq.RenderContext; +// ... import org.jooq.SQLDialect; import org.jooq.Select; import org.jooq.Table; @@ -81,6 +83,11 @@ import org.jooq.conf.Settings; import org.jooq.conf.SettingsTools; import org.jooq.exception.ControlFlowSignal; import org.jooq.exception.DataAccessException; +import org.jooq.impl.QOM.BitNot; +import org.jooq.impl.QOM.Ltrim; +import org.jooq.impl.QOM.Neg; +import org.jooq.impl.QOM.Not; +import org.jooq.impl.QOM.Rtrim; import org.jooq.impl.ScopeMarker.ScopeContent; import org.jooq.tools.JooqLogger; import org.jooq.tools.StringUtils; @@ -703,13 +710,19 @@ class DefaultRenderContext extends AbstractContext implements Ren @Override protected final void visit0(QueryPartInternal internal) { - if (isQuery == null) + if (isQuery == null) { isQuery = internal instanceof Query; + } + + + + + @@ -780,6 +793,66 @@ class DefaultRenderContext extends AbstractContext implements Ren } } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + private final void checkForceInline(int max) throws ForceInlineSignal { if (bindValues.size() > max) if (TRUE.equals(data(DATA_COUNT_BIND_VALUES))) diff --git a/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.17.0.xsd b/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.17.0.xsd index 5afebfd166..8cffb83c14 100644 --- a/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.17.0.xsd +++ b/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.17.0.xsd @@ -269,6 +269,65 @@ Using this flag, fetching of intermediate results can be turned off even when ex are present, or turned on even if they're absent.]]> + + +This flag enables the pattern transformation feature, which consists of several sub-flags that are +all prefixed with "transformPatterns", e.g. {@link #transformPatternsTrim}. While the sub-flags default +to being enabled, and can be disabled on an individual basis, the global feature itself is disabled by +default. +

+This feature is available in the commercial distribution only.]]> + + + + LTRIM(RTRIM(x)) or RTRIM(LTRIM(x)) to TRIM(x) +

+Historically, a few dialects did not implement TRIM(x) or TRIM(BOTH FROM x), +so users worked around this by wrapping LTRIM() and RTRIM() with each other. +Maintaining this is usually undesirable, so this transformation helps remove the unwanted wrapping. +

+To enable this feature, {@link #transformPatterns} must be enabled as well. +

+This feature is available in the commercial distribution only.]]> + + + + NOT(NOT(x)) to x +

+For various reasons, there may be a redundant nesting of NOT unary operators, e.g. as a +left over of some prior transformation, including manual ones. This transformation will simplify such +redundant negations by removing them. +

+To enable this feature, {@link #transformPatterns} must be enabled as well. +

+This feature is available in the commercial distribution only.]]> + + + + -(-(x)) to x +

+For various reasons, there may be a redundant nesting of - unary operators, e.g. as a +left over of some prior transformation, including manual ones. This transformation will simplify such +redundant negations by removing them. +

+To enable this feature, {@link #transformPatterns} must be enabled as well. +

+This feature is available in the commercial distribution only.]]> + + + + ~(~(x)) to x +

+For various reasons, there may be a redundant nesting of ~ unary operators, e.g. as a +left over of some prior transformation, including manual ones. This transformation will simplify such +redundant negations by removing them. +

+To enable this feature, {@link #transformPatterns} must be enabled as well. +

+This feature is available in the commercial distribution only.]]> + +