diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractCondition.java b/jOOQ/src/main/java/org/jooq/impl/AbstractCondition.java index 223668a1d6..bef3177495 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractCondition.java @@ -63,6 +63,15 @@ abstract class AbstractCondition extends AbstractQueryPart implements Condition AbstractCondition() {} + /** + * [#10179] Subclasses may override this method to indicate that the + * condition may produce TRUE, FALSE, or + * NULL. + */ + boolean isNullable() { + return true; + } + @Override public Clause[] clauses(Context ctx) { return CLAUSES; diff --git a/jOOQ/src/main/java/org/jooq/impl/CombinedCondition.java b/jOOQ/src/main/java/org/jooq/impl/CombinedCondition.java index f27064bf04..d558662168 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CombinedCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/CombinedCondition.java @@ -110,6 +110,15 @@ final class CombinedCondition extends AbstractCondition { return falseCondition(); } + @Override + final boolean isNullable() { + for (Condition condition : conditions) + if (!(condition instanceof AbstractCondition) || ((AbstractCondition) condition).isNullable()) + return true; + + return false; + } + private CombinedCondition(Operator operator, int size) { if (operator == null) throw new IllegalArgumentException("The argument 'operator' must not be null"); diff --git a/jOOQ/src/main/java/org/jooq/impl/ConditionAsField.java b/jOOQ/src/main/java/org/jooq/impl/ConditionAsField.java index 3b9cb41870..8b7efaf775 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ConditionAsField.java +++ b/jOOQ/src/main/java/org/jooq/impl/ConditionAsField.java @@ -81,15 +81,14 @@ final class ConditionAsField extends AbstractField { // [#10179] Avoid 3VL when not necessary - if (condition instanceof NotNullCondition) + if (condition instanceof AbstractCondition && !((AbstractCondition) condition).isNullable()) ctx.visit(DSL.when(condition, inline(true)) .else_(inline(false))); // [#3206] Implement 3VL if necessary or unknown else ctx.visit(DSL.when(condition, inline(true)) - .when(not(condition), inline(false)) - .else_(inline((Boolean) null))); + .when(not(condition), inline(false))); break; // These databases can inline predicates in column expression contexts diff --git a/jOOQ/src/main/java/org/jooq/impl/ExistsCondition.java b/jOOQ/src/main/java/org/jooq/impl/ExistsCondition.java index b6e1a3505d..57aa5e6689 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ExistsCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/ExistsCondition.java @@ -51,7 +51,7 @@ import org.jooq.Select; /** * @author Lukas Eder */ -final class ExistsCondition extends AbstractCondition implements NotNullCondition { +final class ExistsCondition extends AbstractCondition { private static final long serialVersionUID = 5678338161136603292L; private static final Clause[] CLAUSES_EXISTS = { CONDITION, CONDITION_EXISTS }; @@ -65,6 +65,11 @@ final class ExistsCondition extends AbstractCondition implements NotNullConditio this.exists = exists; } + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { ctx.visit(exists ? K_EXISTS : K_NOT_EXISTS) diff --git a/jOOQ/src/main/java/org/jooq/impl/FalseCondition.java b/jOOQ/src/main/java/org/jooq/impl/FalseCondition.java index ef03d5f40d..4bf848ae7b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FalseCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/FalseCondition.java @@ -53,6 +53,11 @@ final class FalseCondition extends AbstractCondition implements False { private static final Clause[] CLAUSES = { CONDITION, CONDITION_COMPARISON }; static final FalseCondition INSTANCE = new FalseCondition(); + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { ctx.sql("1 = 0"); diff --git a/jOOQ/src/main/java/org/jooq/impl/IsDistinctFrom.java b/jOOQ/src/main/java/org/jooq/impl/IsDistinctFrom.java index 33bb2789d3..a0d19d5686 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsDistinctFrom.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsDistinctFrom.java @@ -81,7 +81,7 @@ import org.jooq.SQLDialect; /** * @author Lukas Eder */ -final class IsDistinctFrom extends AbstractCondition implements NotNullCondition { +final class IsDistinctFrom extends AbstractCondition { /** @@ -105,6 +105,11 @@ final class IsDistinctFrom extends AbstractCondition implements NotNullCondit this.comparator = comparator; } + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { if (isEmbeddable(lhs) && isEmbeddable(rhs)) diff --git a/jOOQ/src/main/java/org/jooq/impl/IsDocument.java b/jOOQ/src/main/java/org/jooq/impl/IsDocument.java index 4ea58f6d15..4ebdde44c9 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsDocument.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsDocument.java @@ -47,7 +47,7 @@ import org.jooq.Field; /** * @author Lukas Eder */ -final class IsDocument extends AbstractCondition implements NotNullCondition { +final class IsDocument extends AbstractCondition { /** * Generated UID @@ -61,6 +61,11 @@ final class IsDocument extends AbstractCondition implements NotNullCondition { this.isDocument = isDocument; } + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { ctx.visit(field).sql(' ').visit(isDocument ? K_IS_DOCUMENT : K_IS_NOT_DOCUMENT); diff --git a/jOOQ/src/main/java/org/jooq/impl/IsJSON.java b/jOOQ/src/main/java/org/jooq/impl/IsJSON.java index bd12b8370f..5b90c642a9 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsJSON.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsJSON.java @@ -51,7 +51,7 @@ import org.jooq.Field; /** * @author Lukas Eder */ -final class IsJSON extends AbstractCondition implements NotNullCondition { +final class IsJSON extends AbstractCondition { /** * Generated UID @@ -65,6 +65,11 @@ final class IsJSON extends AbstractCondition implements NotNullCondition { this.isJSON = isJSON; } + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { switch (ctx.family()) { diff --git a/jOOQ/src/main/java/org/jooq/impl/IsNull.java b/jOOQ/src/main/java/org/jooq/impl/IsNull.java index a6c6205545..1f1ff3ea73 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsNull.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsNull.java @@ -54,7 +54,7 @@ import org.jooq.Field; /** * @author Lukas Eder */ -final class IsNull extends AbstractCondition implements NotNullCondition { +final class IsNull extends AbstractCondition { private static final long serialVersionUID = -747240442279619486L; private static final Clause[] CLAUSES_NULL = { CONDITION, CONDITION_IS_NULL }; @@ -68,6 +68,11 @@ final class IsNull extends AbstractCondition implements NotNullCondition { this.isNull = isNull; } + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { if (isEmbeddable(field)) diff --git a/jOOQ/src/main/java/org/jooq/impl/NoCondition.java b/jOOQ/src/main/java/org/jooq/impl/NoCondition.java index bf3a929221..78ab38282f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/NoCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/NoCondition.java @@ -53,6 +53,11 @@ final class NoCondition extends AbstractCondition { private static final Clause[] CLAUSES = { CONDITION, CONDITION_COMPARISON }; static final NoCondition INSTANCE = new NoCondition(); + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { ctx.sql("1 = 1"); diff --git a/jOOQ/src/main/java/org/jooq/impl/NotCondition.java b/jOOQ/src/main/java/org/jooq/impl/NotCondition.java index 1ee79ab20b..215d328ea0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/NotCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/NotCondition.java @@ -56,9 +56,14 @@ final class NotCondition extends AbstractCondition { this.condition = condition; } + @Override + boolean isNullable() { + return !(condition instanceof AbstractCondition) || ((AbstractCondition) condition).isNullable(); + } + @Override public final void accept(Context ctx) { - ctx.visit(K_NOT).sql('(').visit(condition).sql(')'); + ctx.visit(K_NOT).sql(" (").visit(condition).sql(')'); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/NotNullCondition.java b/jOOQ/src/main/java/org/jooq/impl/NotNullCondition.java deleted file mode 100644 index c614500c6f..0000000000 --- a/jOOQ/src/main/java/org/jooq/impl/NotNullCondition.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Other licenses: - * ----------------------------------------------------------------------------- - * Commercial licenses for this work are available. These replace the above - * ASL 2.0 and offer limited warranties, support, maintenance, and commercial - * database integrations. - * - * For more information, please visit: http://www.jooq.org/licenses - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ -package org.jooq.impl; - -/** - * A marker interface for conditions that can only be TRUE or - * FALSE, never NULL. - * - * @author Lukas Eder - */ -interface NotNullCondition {} diff --git a/jOOQ/src/main/java/org/jooq/impl/RowIsDistinctFrom.java b/jOOQ/src/main/java/org/jooq/impl/RowIsDistinctFrom.java index 7105cecb90..6542e91fa0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/RowIsDistinctFrom.java +++ b/jOOQ/src/main/java/org/jooq/impl/RowIsDistinctFrom.java @@ -75,7 +75,7 @@ import org.jooq.SQLDialect; /** * @author Lukas Eder */ -final class RowIsDistinctFrom extends AbstractCondition implements NotNullCondition { +final class RowIsDistinctFrom extends AbstractCondition { /** * Generated UID @@ -98,6 +98,11 @@ final class RowIsDistinctFrom extends AbstractCondition implements NotNullCondit this.not = not; } + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { ctx.visit(delegate(ctx.configuration())); diff --git a/jOOQ/src/main/java/org/jooq/impl/RowIsNull.java b/jOOQ/src/main/java/org/jooq/impl/RowIsNull.java index 8ec8d9bc54..55c5273f87 100644 --- a/jOOQ/src/main/java/org/jooq/impl/RowIsNull.java +++ b/jOOQ/src/main/java/org/jooq/impl/RowIsNull.java @@ -82,7 +82,7 @@ import org.jooq.Table; /** * @author Lukas Eder */ -final class RowIsNull extends AbstractCondition implements NotNullCondition { +final class RowIsNull extends AbstractCondition { /** * Generated UID @@ -110,6 +110,11 @@ final class RowIsNull extends AbstractCondition implements NotNullCondition { this.isNull = isNull; } + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { diff --git a/jOOQ/src/main/java/org/jooq/impl/TrueCondition.java b/jOOQ/src/main/java/org/jooq/impl/TrueCondition.java index 22dd0f63e5..cf8a92f3cc 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TrueCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/TrueCondition.java @@ -54,6 +54,11 @@ final class TrueCondition extends AbstractCondition implements True { private static final Clause[] CLAUSES = { CONDITION, CONDITION_COMPARISON }; static final TrueCondition INSTANCE = new TrueCondition(); + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { ctx.sql("1 = 1"); diff --git a/jOOQ/src/main/java/org/jooq/impl/UniqueCondition.java b/jOOQ/src/main/java/org/jooq/impl/UniqueCondition.java index a3f5d76ab2..250e0554f4 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UniqueCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/UniqueCondition.java @@ -54,7 +54,7 @@ import org.jooq.Table; /** * @author Knut Wannheden */ -final class UniqueCondition extends AbstractCondition implements NotNullCondition { +final class UniqueCondition extends AbstractCondition { private static final long serialVersionUID = -5560973283201522844L; @@ -66,6 +66,11 @@ final class UniqueCondition extends AbstractCondition implements NotNullConditio this.unique = unique; } + @Override + final boolean isNullable() { + return false; + } + @Override public final void accept(Context ctx) { ctx.visit(delegate(ctx));