diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/PredicateTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/PredicateTests.java index eb6caaf7ff..c3aa1120d7 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/PredicateTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/PredicateTests.java @@ -407,6 +407,8 @@ extends BaseTest extends NamedTypeProviderQueryPart, AliasProvider minValue, Field maxValue); + /** + * Create a condition to check this field against some bounds + *

+ * SQL: this between symmetric minValue and maxValue + */ + @Support + Condition betweenSymmetric(T minValue, T maxValue); + + /** + * Create a condition to check this field against some bounds + *

+ * SQL: this between symmetric minValue and maxValue + */ + @Support + Condition betweenSymmetric(Field minValue, Field maxValue); + /** * Create a condition to check this field against some bounds *

@@ -1108,6 +1124,22 @@ public interface Field extends NamedTypeProviderQueryPart, AliasProvider minValue, Field maxValue); + /** + * Create a condition to check this field against some bounds + *

+ * SQL: this not between symmetric minValue and maxValue + */ + @Support + Condition notBetweenSymmetric(T minValue, T maxValue); + + /** + * Create a condition to check this field against some bounds + *

+ * SQL: this not between symmetric minValue and maxValue + */ + @Support + Condition notBetweenSymmetric(Field minValue, Field maxValue); + // ------------------------------------------------------------------------ // Comparison predicates // ------------------------------------------------------------------------ diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java index 4d41f4152d..c8241b53af 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java @@ -545,7 +545,17 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im @Override public final Condition between(Field minValue, Field maxValue) { - return new BetweenCondition(this, nullSafe(minValue), nullSafe(maxValue), false); + return new BetweenCondition(this, nullSafe(minValue), nullSafe(maxValue), false, false); + } + + @Override + public final Condition betweenSymmetric(T minValue, T maxValue) { + return betweenSymmetric(val(minValue, this), val(maxValue, this)); + } + + @Override + public final Condition betweenSymmetric(Field minValue, Field maxValue) { + return new BetweenCondition(this, nullSafe(minValue), nullSafe(maxValue), false, true); } @Override @@ -555,7 +565,17 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im @Override public final Condition notBetween(Field minValue, Field maxValue) { - return new BetweenCondition(this, nullSafe(minValue), nullSafe(maxValue), true); + return new BetweenCondition(this, nullSafe(minValue), nullSafe(maxValue), true, false); + } + + @Override + public final Condition notBetweenSymmetric(T minValue, T maxValue) { + return notBetweenSymmetric(val(minValue, this), val(maxValue, this)); + } + + @Override + public final Condition notBetweenSymmetric(Field minValue, Field maxValue) { + return new BetweenCondition(this, nullSafe(minValue), nullSafe(maxValue), true, true); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/BetweenCondition.java b/jOOQ/src/main/java/org/jooq/impl/BetweenCondition.java index 7213788cfa..56d7e1aed1 100644 --- a/jOOQ/src/main/java/org/jooq/impl/BetweenCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/BetweenCondition.java @@ -36,8 +36,19 @@ package org.jooq.impl; +import static java.util.Arrays.asList; +import static org.jooq.SQLDialect.CUBRID; +import static org.jooq.SQLDialect.DB2; +import static org.jooq.SQLDialect.DERBY; +import static org.jooq.SQLDialect.H2; +import static org.jooq.SQLDialect.MYSQL; +import static org.jooq.SQLDialect.ORACLE; +import static org.jooq.SQLDialect.SQLITE; +import static org.jooq.SQLDialect.SQLSERVER; + import org.jooq.BindContext; import org.jooq.Field; +import org.jooq.QueryPartInternal; import org.jooq.RenderContext; /** @@ -47,30 +58,54 @@ class BetweenCondition extends AbstractCondition { private static final long serialVersionUID = -4666251100802237878L; + private final boolean symmetric; private final boolean not; private final Field field; private final Field minValue; private final Field maxValue; - BetweenCondition(Field field, Field minValue, Field maxValue, boolean not) { + BetweenCondition(Field field, Field minValue, Field maxValue, boolean not, boolean symmetric) { this.field = field; this.minValue = minValue; this.maxValue = maxValue; this.not = not; + this.symmetric = symmetric; } @Override public final void bind(BindContext context) { - context.bind(field).bind(minValue).bind(maxValue); + if (symmetric && asList(CUBRID, DB2, DERBY, H2, MYSQL, ORACLE, SQLSERVER, SQLITE).contains(context.getDialect())) { + simulateSymmetric().bind(context); + } + else { + context.bind(field).bind(minValue).bind(maxValue); + } } @Override public final void toSQL(RenderContext context) { - context.sql(field) - .keyword(not ? " not" : "") - .keyword(" between ") - .sql(minValue) - .keyword(" and ") - .sql(maxValue); + + // TODO: Sybase SQL Anywhere? Sybase ASE + if (symmetric && asList(CUBRID, DB2, DERBY, H2, MYSQL, ORACLE, SQLSERVER, SQLITE).contains(context.getDialect())) { + simulateSymmetric().toSQL(context); + } + else { + context.sql(field) + .keyword(not ? " not" : "") + .keyword(" between ") + .keyword(symmetric ? "symmetric " : "") + .sql(minValue) + .keyword(" and ") + .sql(maxValue); + } + } + + private final QueryPartInternal simulateSymmetric() { + if (not) { + return (QueryPartInternal) field.notBetween(minValue, maxValue).and(field.notBetween(maxValue, minValue)); + } + else { + return (QueryPartInternal) field.between(minValue, maxValue).or(field.between(maxValue, minValue)); + } } } diff --git a/jOOQ/src/test/java/org/jooq/test/jOOQTest.java b/jOOQ/src/test/java/org/jooq/test/jOOQTest.java index 8a0074aa7b..08522379ad 100644 --- a/jOOQ/src/test/java/org/jooq/test/jOOQTest.java +++ b/jOOQ/src/test/java/org/jooq/test/jOOQTest.java @@ -211,6 +211,9 @@ public class jOOQTest { assertEquals( FIELD_ID1.between((Integer) null, null), FIELD_ID1.between((Field) null, null)); + assertEquals( + FIELD_ID1.betweenSymmetric((Integer) null, null), + FIELD_ID1.betweenSymmetric((Field) null, null)); assertEquals( FIELD_ID1.div((Integer) null), FIELD_ID1.div((Field) null)); @@ -244,6 +247,12 @@ public class jOOQTest { assertEquals( FIELD_ID1.mul((Integer) null), FIELD_ID1.mul((Field) null)); + assertEquals( + FIELD_ID1.notBetween((Integer) null, null), + FIELD_ID1.notBetween((Field) null, null)); + assertEquals( + FIELD_ID1.notBetweenSymmetric((Integer) null, null), + FIELD_ID1.notBetweenSymmetric((Field) null, null)); assertEquals( FIELD_ID1.notEqual((Integer) null), FIELD_ID1.notEqual((Field) null));