From 1ca748ffc16d4c3f585651a89c269e941db24cbd Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 27 Oct 2022 17:12:20 +0200 Subject: [PATCH] [jOOQ/jOOQ#13593] Implement more transform patterns - Settings.transformPatternsCaseMergeWhenElse - Settings.transformPatternsCaseMergeWhenWhen --- .../src/main/java/org/jooq/conf/Settings.java | 140 ++++++++++++++++++ .../src/main/java/org/jooq/impl/Patterns.java | 45 ++++++ jOOQ/src/main/java/org/jooq/impl/QOM.java | 53 ++++++- .../org/jooq/xsd/jooq-runtime-3.18.0.xsd | 26 ++++ 4 files changed, 263 insertions(+), 1 deletion(-) diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java index 2d48c537db..1765a33e7e 100644 --- a/jOOQ/src/main/java/org/jooq/conf/Settings.java +++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java @@ -179,6 +179,12 @@ public class Settings @XmlElement(defaultValue = "true") protected Boolean transformPatternsCaseElseCase = true; @XmlElement(defaultValue = "true") + protected Boolean transformPatternsCaseMergeWhenWhen = true; + @XmlElement(defaultValue = "true") + protected Boolean transformPatternsCaseMergeWhenElse = true; + @XmlElement(defaultValue = "true") + protected Boolean transformPatternsCaseThenBoolean = true; + @XmlElement(defaultValue = "true") protected Boolean transformPatternsTrivialCaseAbbreviation = true; @XmlElement(defaultValue = "true") protected Boolean transformPatternsTrivialPredicates = true; @@ -2169,6 +2175,92 @@ public class Settings this.transformPatternsCaseElseCase = value; } + /** + * Transform CASE WHEN a THEN x WHEN b THEN x END to CASE WHEN a OR b THEN x END. + *

+ * Two consecutive WHEN clauses can be merged, if their respective THEN clause is identical. + *

+ * This feature is available in the commercial distribution only. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isTransformPatternsCaseMergeWhenWhen() { + return transformPatternsCaseMergeWhenWhen; + } + + /** + * Sets the value of the transformPatternsCaseMergeWhenWhen property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setTransformPatternsCaseMergeWhenWhen(Boolean value) { + this.transformPatternsCaseMergeWhenWhen = value; + } + + /** + * Transform CASE WHEN a THEN x WHEN b THEN y ELSE y END to CASE WHEN a THEN x ELSE y END. + *

+ * The ultimate WHEN clause can be merged with the ELSE, if their respective result is identical. + * If the WHEN clause is the only WHEN clause, then the entire CASE expression can + * be replaced by the ELSE clause content. + *

+ * This feature is available in the commercial distribution only. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isTransformPatternsCaseMergeWhenElse() { + return transformPatternsCaseMergeWhenElse; + } + + /** + * Sets the value of the transformPatternsCaseMergeWhenElse property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setTransformPatternsCaseMergeWhenElse(Boolean value) { + this.transformPatternsCaseMergeWhenElse = value; + } + + /** + * Transform CASE … THEN TRUE ELSE FALSE to something simpler. + *

+ * A CASE expression that transforms things to booleans can usually be simplified easily. + *

+ * This feature is available in the commercial distribution only. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isTransformPatternsCaseThenBoolean() { + return transformPatternsCaseThenBoolean; + } + + /** + * Sets the value of the transformPatternsCaseThenBoolean property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setTransformPatternsCaseThenBoolean(Boolean value) { + this.transformPatternsCaseThenBoolean = value; + } + /** * Transform trivial case abbreviations like NVL(NULL, a) to a. *

@@ -5196,6 +5288,21 @@ public class Settings return this; } + public Settings withTransformPatternsCaseMergeWhenWhen(Boolean value) { + setTransformPatternsCaseMergeWhenWhen(value); + return this; + } + + public Settings withTransformPatternsCaseMergeWhenElse(Boolean value) { + setTransformPatternsCaseMergeWhenElse(value); + return this; + } + + public Settings withTransformPatternsCaseThenBoolean(Boolean value) { + setTransformPatternsCaseThenBoolean(value); + return this; + } + public Settings withTransformPatternsTrivialCaseAbbreviation(Boolean value) { setTransformPatternsTrivialCaseAbbreviation(value); return this; @@ -6176,6 +6283,9 @@ public class Settings builder.append("transformPatternsMergeBetweenSymmetricPredicates", transformPatternsMergeBetweenSymmetricPredicates); builder.append("transformPatternsCaseElseNull", transformPatternsCaseElseNull); builder.append("transformPatternsCaseElseCase", transformPatternsCaseElseCase); + builder.append("transformPatternsCaseMergeWhenWhen", transformPatternsCaseMergeWhenWhen); + builder.append("transformPatternsCaseMergeWhenElse", transformPatternsCaseMergeWhenElse); + builder.append("transformPatternsCaseThenBoolean", transformPatternsCaseThenBoolean); builder.append("transformPatternsTrivialCaseAbbreviation", transformPatternsTrivialCaseAbbreviation); builder.append("transformPatternsTrivialPredicates", transformPatternsTrivialPredicates); builder.append("transformPatternsScalarSubqueryCountAsteriskGtZero", transformPatternsScalarSubqueryCountAsteriskGtZero); @@ -6889,6 +6999,33 @@ public class Settings return false; } } + if (transformPatternsCaseMergeWhenWhen == null) { + if (other.transformPatternsCaseMergeWhenWhen!= null) { + return false; + } + } else { + if (!transformPatternsCaseMergeWhenWhen.equals(other.transformPatternsCaseMergeWhenWhen)) { + return false; + } + } + if (transformPatternsCaseMergeWhenElse == null) { + if (other.transformPatternsCaseMergeWhenElse!= null) { + return false; + } + } else { + if (!transformPatternsCaseMergeWhenElse.equals(other.transformPatternsCaseMergeWhenElse)) { + return false; + } + } + if (transformPatternsCaseThenBoolean == null) { + if (other.transformPatternsCaseThenBoolean!= null) { + return false; + } + } else { + if (!transformPatternsCaseThenBoolean.equals(other.transformPatternsCaseThenBoolean)) { + return false; + } + } if (transformPatternsTrivialCaseAbbreviation == null) { if (other.transformPatternsTrivialCaseAbbreviation!= null) { return false; @@ -8004,6 +8141,9 @@ public class Settings result = ((prime*result)+((transformPatternsMergeBetweenSymmetricPredicates == null)? 0 :transformPatternsMergeBetweenSymmetricPredicates.hashCode())); result = ((prime*result)+((transformPatternsCaseElseNull == null)? 0 :transformPatternsCaseElseNull.hashCode())); result = ((prime*result)+((transformPatternsCaseElseCase == null)? 0 :transformPatternsCaseElseCase.hashCode())); + result = ((prime*result)+((transformPatternsCaseMergeWhenWhen == null)? 0 :transformPatternsCaseMergeWhenWhen.hashCode())); + result = ((prime*result)+((transformPatternsCaseMergeWhenElse == null)? 0 :transformPatternsCaseMergeWhenElse.hashCode())); + result = ((prime*result)+((transformPatternsCaseThenBoolean == null)? 0 :transformPatternsCaseThenBoolean.hashCode())); result = ((prime*result)+((transformPatternsTrivialCaseAbbreviation == null)? 0 :transformPatternsTrivialCaseAbbreviation.hashCode())); result = ((prime*result)+((transformPatternsTrivialPredicates == null)? 0 :transformPatternsTrivialPredicates.hashCode())); result = ((prime*result)+((transformPatternsScalarSubqueryCountAsteriskGtZero == null)? 0 :transformPatternsScalarSubqueryCountAsteriskGtZero.hashCode())); diff --git a/jOOQ/src/main/java/org/jooq/impl/Patterns.java b/jOOQ/src/main/java/org/jooq/impl/Patterns.java index 5110b2274f..80f1262241 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Patterns.java +++ b/jOOQ/src/main/java/org/jooq/impl/Patterns.java @@ -1717,6 +1717,51 @@ package org.jooq.impl; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/QOM.java b/jOOQ/src/main/java/org/jooq/impl/QOM.java index 543fb3dc4d..f576d7da98 100644 --- a/jOOQ/src/main/java/org/jooq/impl/QOM.java +++ b/jOOQ/src/main/java/org/jooq/impl/QOM.java @@ -252,10 +252,61 @@ public final class QOM { permits QueryPartListView { + + // TODO: These methods could return unmodifiable views instead, to avoid + // copying things around... @NotNull default UnmodifiableList $concat(UnmodifiableList other) { QueryPartList r = new QueryPartList<>(this); r.addAll(other); - return r; + return unmodifiable(r); + } + + @NotNull default UnmodifiableList $removeFirst() { + QueryPartList r = new QueryPartList<>(); + + for (int i = 1; i < size(); i++) + r.add(get(i)); + + return unmodifiable(r); + } + + @NotNull default UnmodifiableList $set(int position, Q newValue) { + QueryPartList r = new QueryPartList<>(); + + for (int i = 0; i < size(); i++) + if (i == position) + r.add(newValue); + else + r.add(get(i)); + + return unmodifiable(r); + } + + @NotNull default UnmodifiableList $remove(int position) { + QueryPartList r = new QueryPartList<>(); + + for (int i = 0; i < size(); i++) + if (i != position) + r.add(get(i)); + + return unmodifiable(r); + } + + @NotNull default UnmodifiableList $removeLast() { + QueryPartList r = new QueryPartList<>(); + + for (int i = 0; i < size() - 1; i++) + r.add(get(i)); + + return unmodifiable(r); + } + + @Nullable default Q $first() { + return isEmpty() ? null : get(0); + } + + @Nullable default Q $last() { + return isEmpty() ? null : get(size() - 1); } } diff --git a/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.18.0.xsd b/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.18.0.xsd index c32981d557..145e33a7db 100644 --- a/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.18.0.xsd +++ b/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.18.0.xsd @@ -568,6 +568,32 @@ This feature is available in the commercial distribution only.]]>< This feature is available in the commercial distribution only.]]> + + CASE WHEN a THEN x WHEN b THEN x END to CASE WHEN a OR b THEN x END. +

+Two consecutive WHEN clauses can be merged, if their respective THEN clause is identical. +

+This feature is available in the commercial distribution only.]]> + + + + CASE WHEN a THEN x WHEN b THEN y ELSE y END to CASE WHEN a THEN x ELSE y END. +

+The ultimate WHEN clause can be merged with the ELSE, if their respective result is identical. +If the WHEN clause is the only WHEN clause, then the entire CASE expression can +be replaced by the ELSE clause content. +

+This feature is available in the commercial distribution only.]]> + + + + CASE .. THEN TRUE ELSE FALSE to something simpler. +

+A CASE expression that transforms things to booleans can usually be simplified easily. +

+This feature is available in the commercial distribution only.]]> + + NVL(NULL, a) to a.