[#1698] Add support for the SQL standard BETWEEN SYMMETRIC predicate

This commit is contained in:
Lukas Eder 2012-08-11 13:33:27 +02:00
parent 68cfc2d7cd
commit 3c9ae4da6e
6 changed files with 111 additions and 11 deletions

View File

@ -407,6 +407,8 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658,
assertEquals(Arrays.asList(2, 3), create().select()
.from(TBook())
.where(TBook_ID().between(2, 3))
.and(TBook_ID().betweenSymmetric(2, 3))
.and(TBook_ID().betweenSymmetric(3, 2))
.orderBy(TBook_ID()).fetch(TBook_ID()));
assertEquals(Arrays.asList(3, 4), create().select()
@ -418,6 +420,8 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658,
assertEquals(Arrays.asList(1, 4), create().select()
.from(TBook())
.where(TBook_ID().notBetween(2, 3))
.and(TBook_ID().notBetweenSymmetric(2, 3))
.and(TBook_ID().notBetweenSymmetric(3, 2))
.orderBy(TBook_ID()).fetch(TBook_ID()));
assertEquals(Arrays.asList(1, 2), create().select()

View File

@ -377,7 +377,7 @@ public abstract class jOOQAbstractTest<
autocommit = connection.getAutoCommit();
if (!initialised) {
if (false && !initialised) {
initialised = true;
execute(getCreateScript());
}

View File

@ -1092,6 +1092,22 @@ public interface Field<T> extends NamedTypeProviderQueryPart<T>, AliasProvider<F
@Support
Condition between(Field<T> minValue, Field<T> maxValue);
/**
* Create a condition to check this field against some bounds
* <p>
* SQL: <code>this between symmetric minValue and maxValue</code>
*/
@Support
Condition betweenSymmetric(T minValue, T maxValue);
/**
* Create a condition to check this field against some bounds
* <p>
* SQL: <code>this between symmetric minValue and maxValue</code>
*/
@Support
Condition betweenSymmetric(Field<T> minValue, Field<T> maxValue);
/**
* Create a condition to check this field against some bounds
* <p>
@ -1108,6 +1124,22 @@ public interface Field<T> extends NamedTypeProviderQueryPart<T>, AliasProvider<F
@Support
Condition notBetween(Field<T> minValue, Field<T> maxValue);
/**
* Create a condition to check this field against some bounds
* <p>
* SQL: <code>this not between symmetric minValue and maxValue</code>
*/
@Support
Condition notBetweenSymmetric(T minValue, T maxValue);
/**
* Create a condition to check this field against some bounds
* <p>
* SQL: <code>this not between symmetric minValue and maxValue</code>
*/
@Support
Condition notBetweenSymmetric(Field<T> minValue, Field<T> maxValue);
// ------------------------------------------------------------------------
// Comparison predicates
// ------------------------------------------------------------------------

View File

@ -545,7 +545,17 @@ abstract class AbstractField<T> extends AbstractNamedTypeProviderQueryPart<T> im
@Override
public final Condition between(Field<T> minValue, Field<T> maxValue) {
return new BetweenCondition<T>(this, nullSafe(minValue), nullSafe(maxValue), false);
return new BetweenCondition<T>(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<T> minValue, Field<T> maxValue) {
return new BetweenCondition<T>(this, nullSafe(minValue), nullSafe(maxValue), false, true);
}
@Override
@ -555,7 +565,17 @@ abstract class AbstractField<T> extends AbstractNamedTypeProviderQueryPart<T> im
@Override
public final Condition notBetween(Field<T> minValue, Field<T> maxValue) {
return new BetweenCondition<T>(this, nullSafe(minValue), nullSafe(maxValue), true);
return new BetweenCondition<T>(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<T> minValue, Field<T> maxValue) {
return new BetweenCondition<T>(this, nullSafe(minValue), nullSafe(maxValue), true, true);
}
@Override

View File

@ -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<T> extends AbstractCondition {
private static final long serialVersionUID = -4666251100802237878L;
private final boolean symmetric;
private final boolean not;
private final Field<T> field;
private final Field<T> minValue;
private final Field<T> maxValue;
BetweenCondition(Field<T> field, Field<T> minValue, Field<T> maxValue, boolean not) {
BetweenCondition(Field<T> field, Field<T> minValue, Field<T> 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));
}
}
}

View File

@ -211,6 +211,9 @@ public class jOOQTest {
assertEquals(
FIELD_ID1.between((Integer) null, null),
FIELD_ID1.between((Field<Integer>) null, null));
assertEquals(
FIELD_ID1.betweenSymmetric((Integer) null, null),
FIELD_ID1.betweenSymmetric((Field<Integer>) null, null));
assertEquals(
FIELD_ID1.div((Integer) null),
FIELD_ID1.div((Field<Integer>) null));
@ -244,6 +247,12 @@ public class jOOQTest {
assertEquals(
FIELD_ID1.mul((Integer) null),
FIELD_ID1.mul((Field<Integer>) null));
assertEquals(
FIELD_ID1.notBetween((Integer) null, null),
FIELD_ID1.notBetween((Field<Integer>) null, null));
assertEquals(
FIELD_ID1.notBetweenSymmetric((Integer) null, null),
FIELD_ID1.notBetweenSymmetric((Field<Integer>) null, null));
assertEquals(
FIELD_ID1.notEqual((Integer) null),
FIELD_ID1.notEqual((Field<Integer>) null));