diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java
index 978d818a2a..a779e64530 100644
--- a/jOOQ/src/main/java/org/jooq/conf/Settings.java
+++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java
@@ -187,6 +187,8 @@ public class Settings
@XmlElement(defaultValue = "true")
protected Boolean transformPatternsCaseUnreachableClauses = true;
@XmlElement(defaultValue = "true")
+ protected Boolean transformPatternsCaseDistinctToDecode = true;
+ @XmlElement(defaultValue = "true")
protected Boolean transformPatternsCaseMergeWhenWhen = true;
@XmlElement(defaultValue = "true")
protected Boolean transformPatternsCaseMergeWhenElse = true;
@@ -2316,6 +2318,41 @@ public class Settings
this.transformPatternsCaseUnreachableClauses = value;
}
+ /**
+ * Transform CASE WHEN a IS NOT DISTINCT FROM b … to an equivalent DECODE function.
+ *
+ * When all WHEN clauses of a CASE expression use the DISTINCT predicate, then the
+ * CASE expression can be transformed into a DECODE function call:
+ *
+ * CASE WHEN a IS NOT DISTINCT FROM b THEN 1 END is equivalent to DECODE(a, b, 1)
+ * CASE WHEN a IS NOT DISTINCT FROM b THEN 1 ELSE 2 END is equivalent to DECODE(a, b, 1, 2)
+ * CASE WHEN a IS NOT DISTINCT FROM b THEN 1 WHEN a IS NOT DISTINCT FROM c THEN 2 END is equivalent to DECODE(a, b, 1, c, 2)
+ * CASE WHEN a IS NOT DISTINCT FROM b THEN 1 WHEN a IS NOT DISTINCT FROM c THEN 2 ELSE 3 END is equivalent to DECODE(a, b, 1, c, 2, 3)
+ *
+ *
+ * This feature is available in the commercial distribution only.
+ *
+ * @return
+ * possible object is
+ * {@link Boolean }
+ *
+ */
+ public Boolean isTransformPatternsCaseDistinctToDecode() {
+ return transformPatternsCaseDistinctToDecode;
+ }
+
+ /**
+ * Sets the value of the transformPatternsCaseDistinctToDecode property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Boolean }
+ *
+ */
+ public void setTransformPatternsCaseDistinctToDecode(Boolean value) {
+ this.transformPatternsCaseDistinctToDecode = value;
+ }
+
/**
* Transform CASE WHEN a THEN x WHEN b THEN x END to CASE WHEN a OR b THEN x END.
*
@@ -5541,6 +5578,11 @@ public class Settings
return this;
}
+ public Settings withTransformPatternsCaseDistinctToDecode(Boolean value) {
+ setTransformPatternsCaseDistinctToDecode(value);
+ return this;
+ }
+
public Settings withTransformPatternsCaseMergeWhenWhen(Boolean value) {
setTransformPatternsCaseMergeWhenWhen(value);
return this;
@@ -6555,6 +6597,7 @@ public class Settings
builder.append("transformPatternsCaseElseNull", transformPatternsCaseElseNull);
builder.append("transformPatternsCaseElseCase", transformPatternsCaseElseCase);
builder.append("transformPatternsCaseUnreachableClauses", transformPatternsCaseUnreachableClauses);
+ builder.append("transformPatternsCaseDistinctToDecode", transformPatternsCaseDistinctToDecode);
builder.append("transformPatternsCaseMergeWhenWhen", transformPatternsCaseMergeWhenWhen);
builder.append("transformPatternsCaseMergeWhenElse", transformPatternsCaseMergeWhenElse);
builder.append("transformPatternsCaseToCaseAbbreviation", transformPatternsCaseToCaseAbbreviation);
@@ -7310,6 +7353,15 @@ public class Settings
return false;
}
}
+ if (transformPatternsCaseDistinctToDecode == null) {
+ if (other.transformPatternsCaseDistinctToDecode!= null) {
+ return false;
+ }
+ } else {
+ if (!transformPatternsCaseDistinctToDecode.equals(other.transformPatternsCaseDistinctToDecode)) {
+ return false;
+ }
+ }
if (transformPatternsCaseMergeWhenWhen == null) {
if (other.transformPatternsCaseMergeWhenWhen!= null) {
return false;
@@ -8483,6 +8535,7 @@ public class Settings
result = ((prime*result)+((transformPatternsCaseElseNull == null)? 0 :transformPatternsCaseElseNull.hashCode()));
result = ((prime*result)+((transformPatternsCaseElseCase == null)? 0 :transformPatternsCaseElseCase.hashCode()));
result = ((prime*result)+((transformPatternsCaseUnreachableClauses == null)? 0 :transformPatternsCaseUnreachableClauses.hashCode()));
+ result = ((prime*result)+((transformPatternsCaseDistinctToDecode == null)? 0 :transformPatternsCaseDistinctToDecode.hashCode()));
result = ((prime*result)+((transformPatternsCaseMergeWhenWhen == null)? 0 :transformPatternsCaseMergeWhenWhen.hashCode()));
result = ((prime*result)+((transformPatternsCaseMergeWhenElse == null)? 0 :transformPatternsCaseMergeWhenElse.hashCode()));
result = ((prime*result)+((transformPatternsCaseToCaseAbbreviation == null)? 0 :transformPatternsCaseToCaseAbbreviation.hashCode()));
diff --git a/jOOQ/src/main/java/org/jooq/impl/CaseImpl.java b/jOOQ/src/main/java/org/jooq/impl/CaseImpl.java
index 186aedc7c1..a9168439e5 100644
--- a/jOOQ/src/main/java/org/jooq/impl/CaseImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/CaseImpl.java
@@ -62,7 +62,7 @@ final class CaseImpl implements Case, UTransient {
@Override
public final CaseValueStep value(Field value) {
- return new CaseValueStepImpl<>(value);
+ return new CaseSimpleValueStep<>(value);
}
@Override
@@ -72,7 +72,7 @@ final class CaseImpl implements Case, UTransient {
@Override
public final CaseConditionStep when(Condition condition, Field result) {
- return new CaseConditionStepImpl<>(condition, result);
+ return new CaseSearched<>(condition, result);
}
@Override
diff --git a/jOOQ/src/main/java/org/jooq/impl/CaseConditionStepImpl.java b/jOOQ/src/main/java/org/jooq/impl/CaseSearched.java
similarity index 90%
rename from jOOQ/src/main/java/org/jooq/impl/CaseConditionStepImpl.java
rename to jOOQ/src/main/java/org/jooq/impl/CaseSearched.java
index 2fcfdae0d0..da10ef549d 100644
--- a/jOOQ/src/main/java/org/jooq/impl/CaseConditionStepImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/CaseSearched.java
@@ -39,6 +39,7 @@ package org.jooq.impl;
import static java.lang.Boolean.TRUE;
// ...
+import static org.jooq.impl.DSL.NULL;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.Keywords.K_CASE;
@@ -64,14 +65,13 @@ import org.jooq.Function2;
import org.jooq.Record1;
// ...
import org.jooq.Select;
-import org.jooq.impl.QOM.CaseSearched;
import org.jooq.impl.QOM.Tuple2;
import org.jooq.impl.QOM.UnmodifiableList;
/**
* @author Lukas Eder
*/
-final class CaseConditionStepImpl
+final class CaseSearched
extends
AbstractField
implements
@@ -80,15 +80,15 @@ implements
{
private final List>> when;
- private Field else_;
+ private Field else_;
- CaseConditionStepImpl(DataType type) {
+ CaseSearched(DataType type) {
super(NQ_CASE, type);
this.when = new QueryPartList<>();
}
- CaseConditionStepImpl(Condition condition, Field result) {
+ CaseSearched(Condition condition, Field result) {
this(result.getDataType());
when(condition, result);
@@ -163,7 +163,14 @@ implements
@Override
public final void accept(Context> ctx) {
- switch (ctx.family()) {
+ if (when.isEmpty()) {
+ if (else_ != null)
+ ctx.visit(else_);
+ else
+ ctx.visit(NULL(getDataType()));
+ }
+ else {
+ switch (ctx.family()) {
@@ -174,9 +181,10 @@ implements
- default:
- acceptNative(ctx);
- break;
+ default:
+ acceptNative(ctx);
+ break;
+ }
}
}
@@ -265,7 +273,7 @@ implements
@Override
public final Function2 super UnmodifiableList extends Tuple2>>, ? super Field, ? extends CaseSearched> $constructor() {
return (w, e) -> {
- CaseConditionStepImpl r = new CaseConditionStepImpl<>(getDataType());
+ CaseSearched r = new CaseSearched<>(getDataType());
w.forEach(t -> r.when(t.$1(), t.$2()));
r.else_(e);
return r;
diff --git a/jOOQ/src/main/java/org/jooq/impl/CaseWhenStepImpl.java b/jOOQ/src/main/java/org/jooq/impl/CaseSimple.java
similarity index 87%
rename from jOOQ/src/main/java/org/jooq/impl/CaseWhenStepImpl.java
rename to jOOQ/src/main/java/org/jooq/impl/CaseSimple.java
index f792548cf0..edd995f384 100644
--- a/jOOQ/src/main/java/org/jooq/impl/CaseWhenStepImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/CaseSimple.java
@@ -38,6 +38,7 @@
package org.jooq.impl;
import static java.lang.Boolean.TRUE;
+import static org.jooq.impl.DSL.NULL;
import static org.jooq.impl.Keywords.K_CASE;
import static org.jooq.impl.Keywords.K_ELSE;
import static org.jooq.impl.Keywords.K_END;
@@ -60,14 +61,13 @@ import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.Function3;
// ...
-import org.jooq.impl.QOM.CaseSimple;
import org.jooq.impl.QOM.Tuple2;
import org.jooq.impl.QOM.UnmodifiableList;
/**
* @author Lukas Eder
*/
-final class CaseWhenStepImpl
+final class CaseSimple
extends
AbstractField
implements
@@ -75,23 +75,23 @@ implements
QOM.CaseSimple
{
- private final Field value;
+ private final Field value;
private final List, Field>> when;
- private Field else_;
+ private Field else_;
- CaseWhenStepImpl(Field value, Field compareValue, Field result) {
+ CaseSimple(Field value, Field compareValue, Field result) {
this(value, result.getDataType());
when(compareValue, result);
}
- CaseWhenStepImpl(Field value, Map extends Field, ? extends Field> map) {
+ CaseSimple(Field value, Map extends Field, ? extends Field> map) {
this(value, dataType(map));
mapFields(map);
}
- CaseWhenStepImpl(Field value, DataType type) {
+ CaseSimple(Field value, DataType type) {
super(NQ_CASE, type);
this.value = value;
@@ -168,7 +168,14 @@ implements
@Override
public final void accept(Context> ctx) {
- switch (ctx.family()) {
+ if (when.isEmpty()) {
+ if (else_ != null)
+ ctx.visit(else_);
+ else
+ ctx.visit(NULL(getDataType()));
+ }
+ else {
+ switch (ctx.family()) {
@@ -179,14 +186,15 @@ implements
- // The DERBY dialect doesn't support the simple CASE clause
- case DERBY:
- acceptSearched(ctx);
- break;
+ // The DERBY dialect doesn't support the simple CASE clause
+ case DERBY:
+ acceptSearched(ctx);
+ break;
- default:
- acceptNative(ctx);
- break;
+ default:
+ acceptNative(ctx);
+ break;
+ }
}
}
@@ -284,7 +292,7 @@ implements
@Override
public final Function3 super Field, ? super UnmodifiableList extends Tuple2, Field>>, ? super Field, ? extends CaseSimple> $constructor() {
return (v, w, e) -> {
- CaseWhenStepImpl r = new CaseWhenStepImpl<>(v, getDataType());
+ CaseSimple r = new CaseSimple<>(v, getDataType());
w.forEach(t -> r.when(t.$1(), t.$2()));
r.else_(e);
return r;
diff --git a/jOOQ/src/main/java/org/jooq/impl/CaseValueStepImpl.java b/jOOQ/src/main/java/org/jooq/impl/CaseSimpleValueStep.java
similarity index 92%
rename from jOOQ/src/main/java/org/jooq/impl/CaseValueStepImpl.java
rename to jOOQ/src/main/java/org/jooq/impl/CaseSimpleValueStep.java
index d2715b5cf1..c763222ce3 100644
--- a/jOOQ/src/main/java/org/jooq/impl/CaseValueStepImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/CaseSimpleValueStep.java
@@ -52,11 +52,11 @@ import org.jooq.impl.QOM.UTransient;
*
* @author Lukas Eder
*/
-final class CaseValueStepImpl implements CaseValueStep, UTransient {
+final class CaseSimpleValueStep implements CaseValueStep, UTransient {
private final Field value;
- CaseValueStepImpl(Field value) {
+ CaseSimpleValueStep(Field value) {
this.value = value;
}
@@ -82,7 +82,7 @@ final class CaseValueStepImpl implements CaseValueStep, UTransient {
@Override
public final CaseWhenStep when(Field compareValue, Field result) {
- return new CaseWhenStepImpl<>(value, compareValue, result);
+ return new CaseSimple<>(value, compareValue, result);
}
@Override
@@ -99,6 +99,6 @@ final class CaseValueStepImpl implements CaseValueStep, UTransient {
@Override
public final CaseWhenStep mapFields(Map extends Field, ? extends Field> fields) {
- return new CaseWhenStepImpl<>(value, fields);
+ return new CaseSimple<>(value, fields);
}
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java b/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java
index 02390a1e57..8d11622525 100644
--- a/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java
@@ -1629,7 +1629,7 @@ implements
for (Entry e : m.updateMap.entrySet()) {
FieldOrRowOrSelect exp = update.updateMap.get(e.getKey());
- if (exp instanceof CaseConditionStepImpl c)
+ if (exp instanceof CaseSearched c)
c.when(negate.and(condition), e.getValue());
// [#10523] [#13325] TODO: ClassCastException when we're using Row here, once supported
diff --git a/jOOQ/src/main/java/org/jooq/impl/Patterns.java b/jOOQ/src/main/java/org/jooq/impl/Patterns.java
index d7954a63aa..4867970dac 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Patterns.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Patterns.java
@@ -2117,6 +2117,64 @@ package org.jooq.impl;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 7816d34185..db5204be9d 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
@@ -615,6 +615,21 @@ Case clauses can be proven to be unreachable, and thus removed:
This feature is available in the commercial distribution only.]]>
+
+ CASE WHEN a IS NOT DISTINCT FROM b .. to an equivalent DECODE function.
+
+When all WHEN clauses of a CASE expression use the DISTINCT predicate, then the
+CASE expression can be transformed into a DECODE function call:
+
+CASE WHEN a IS NOT DISTINCT FROM b THEN 1 END is equivalent to DECODE(a, b, 1)
+CASE WHEN a IS NOT DISTINCT FROM b THEN 1 ELSE 2 END is equivalent to DECODE(a, b, 1, 2)
+CASE WHEN a IS NOT DISTINCT FROM b THEN 1 WHEN a IS NOT DISTINCT FROM c THEN 2 END is equivalent to DECODE(a, b, 1, c, 2)
+CASE WHEN a IS NOT DISTINCT FROM b THEN 1 WHEN a IS NOT DISTINCT FROM c THEN 2 ELSE 3 END is equivalent to DECODE(a, b, 1, c, 2, 3)
+
+
+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.