[#1089] Add Field.contains(), .startsWith(), .endsWith() as a convenience for Field.like() (including escaping)
This commit is contained in:
parent
0a3d532c99
commit
bbd02c1813
@ -8282,13 +8282,36 @@ public abstract class jOOQAbstractTest<
|
||||
assertEquals(1, books.size());
|
||||
assertEquals(5, (int) books.get(0).getValue(TBook_ID()));
|
||||
|
||||
// DERBY doesn't know any REPLACE function, hence only test those
|
||||
// conditions that do not use REPLACE internally
|
||||
boolean derby = getDialect() == DERBY;
|
||||
|
||||
// [#1106] Add checks for Factory.escape() function
|
||||
books =
|
||||
create().selectFrom(TBook())
|
||||
.where(TBook_TITLE().like(concat(val("%"), escape("(%)", '!'), val("%")), '!'))
|
||||
.and(TBook_TITLE().like(concat(val("%"), escape(val("(_)"), '#'), val("%")), '#'))
|
||||
.and(TBook_TITLE().notLike(concat(val("%"), escape("(!%)", '#'), val("%")), '#'))
|
||||
.and(TBook_TITLE().notLike(concat(val("%"), escape(val("(#_)"), '!'), val("%")), '!'))
|
||||
.where(TBook_TITLE().like(concat("%", escape("(%)", '!'), "%"), '!'))
|
||||
.and(derby ? trueCondition() :
|
||||
TBook_TITLE().like(concat(val("%"), escape(val("(_)"), '#'), val("%")), '#'))
|
||||
.and(TBook_TITLE().notLike(concat("%", escape("(!%)", '#'), "%"), '#'))
|
||||
.and(derby ? trueCondition() :
|
||||
TBook_TITLE().notLike(concat(val("%"), escape(val("(#_)"), '!'), val("%")), '!'))
|
||||
.fetch();
|
||||
|
||||
assertEquals(1, books.size());
|
||||
assertEquals(5, (int) books.get(0).getValue(TBook_ID()));
|
||||
|
||||
// [#1089] Add checks for convenience methods
|
||||
books =
|
||||
create().selectFrom(TBook())
|
||||
.where(TBook_TITLE().contains("%"))
|
||||
.and(derby ? trueCondition() :
|
||||
TBook_TITLE().contains(val("(_")))
|
||||
.and(TBook_TITLE().startsWith("About"))
|
||||
.and(derby ? trueCondition() :
|
||||
TBook_TITLE().startsWith(val("Abo")))
|
||||
.and(TBook_TITLE().endsWith("review"))
|
||||
.and(derby ? trueCondition() :
|
||||
TBook_TITLE().endsWith(val("review")))
|
||||
.fetch();
|
||||
|
||||
assertEquals(1, books.size());
|
||||
|
||||
@ -475,6 +475,78 @@ public interface Field<T> extends NamedTypeProviderQueryPart<T>, AliasProvider<F
|
||||
@Support
|
||||
Condition notLike(T value, char escape);
|
||||
|
||||
/**
|
||||
* Convenience method for {@link #like(Object, char)} including proper
|
||||
* adding of wildcards and escaping
|
||||
* <p>
|
||||
* SQL: <code>this like ('%' || escape(value, '\') || '%') escape '\'</code>
|
||||
*
|
||||
* @see Factory#escape(String, char)
|
||||
* @see #like(Object, char)
|
||||
*/
|
||||
@Support
|
||||
Condition contains(T value);
|
||||
|
||||
/**
|
||||
* Convenience method for {@link #like(Object, char)} including proper
|
||||
* adding of wildcards and escaping
|
||||
* <p>
|
||||
* SQL: <code>this like ('%' || escape(value, '\') || '%') escape '\'</code>
|
||||
*
|
||||
* @see Factory#escape(Field, char)
|
||||
* @see #like(Field, char)
|
||||
*/
|
||||
@Support({ ASE, DB2, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE, SQLITE })
|
||||
Condition contains(Field<T> value);
|
||||
|
||||
/**
|
||||
* Convenience method for {@link #like(Object, char)} including proper
|
||||
* adding of wildcards and escaping
|
||||
* <p>
|
||||
* SQL: <code>this like (escape(value, '\') || '%') escape '\'</code>
|
||||
*
|
||||
* @see Factory#escape(String, char)
|
||||
* @see #like(Object, char)
|
||||
*/
|
||||
@Support
|
||||
Condition startsWith(T value);
|
||||
|
||||
/**
|
||||
* Convenience method for {@link #like(Object, char)} including proper
|
||||
* adding of wildcards and escaping
|
||||
* <p>
|
||||
* SQL: <code>this like (escape(value, '\') || '%') escape '\'</code>
|
||||
*
|
||||
* @see Factory#escape(Field, char)
|
||||
* @see #like(Field, char)
|
||||
*/
|
||||
@Support({ ASE, DB2, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE, SQLITE })
|
||||
Condition startsWith(Field<T> value);
|
||||
|
||||
/**
|
||||
* Convenience method for {@link #like(Object, char)} including proper
|
||||
* adding of wildcards and escaping
|
||||
* <p>
|
||||
* SQL: <code>this like ('%' || escape(value, '\')) escape '\'</code>
|
||||
*
|
||||
* @see Factory#escape(String, char)
|
||||
* @see #like(Object, char)
|
||||
*/
|
||||
@Support
|
||||
Condition endsWith(T value);
|
||||
|
||||
/**
|
||||
* Convenience method for {@link #like(Object, char)} including proper
|
||||
* adding of wildcards and escaping
|
||||
* <p>
|
||||
* SQL: <code>this like ('%' || escape(value, '\')) escape '\'</code>
|
||||
*
|
||||
* @see Factory#escape(Field, char)
|
||||
* @see #like(Field, char)
|
||||
*/
|
||||
@Support({ ASE, DB2, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE, SQLITE })
|
||||
Condition endsWith(Field<T> value);
|
||||
|
||||
/**
|
||||
* Create a condition to check this field against several values
|
||||
* <p>
|
||||
|
||||
@ -39,6 +39,7 @@ import static org.jooq.impl.ExpressionOperator.ADD;
|
||||
import static org.jooq.impl.ExpressionOperator.DIVIDE;
|
||||
import static org.jooq.impl.ExpressionOperator.MULTIPLY;
|
||||
import static org.jooq.impl.ExpressionOperator.SUBTRACT;
|
||||
import static org.jooq.impl.Factory.escape;
|
||||
import static org.jooq.impl.Factory.falseCondition;
|
||||
import static org.jooq.impl.Factory.nullSafe;
|
||||
import static org.jooq.impl.Factory.trueCondition;
|
||||
@ -378,6 +379,62 @@ abstract class AbstractField<T> extends AbstractNamedTypeProviderQueryPart<T> im
|
||||
return new CompareCondition<T>(this, nullSafe(value), Comparator.NOT_LIKE, escape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition contains(T value) {
|
||||
Field<String> concat = Factory.concat(
|
||||
Factory.literal("'%'"),
|
||||
Factory.val(escape("" + value, '!')),
|
||||
Factory.literal("'%'"));
|
||||
|
||||
return like(concat.cast(this), '!');
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition contains(Field<T> value) {
|
||||
Field<String> concat = Factory.concat(
|
||||
Factory.literal("'%'"),
|
||||
escape(value.cast(String.class), '!'),
|
||||
Factory.literal("'%'"));
|
||||
|
||||
return like(concat.cast(this), '!');
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition startsWith(T value) {
|
||||
Field<String> concat = Factory.concat(
|
||||
Factory.val(escape("" + value, '!')),
|
||||
Factory.literal("'%'"));
|
||||
|
||||
return like(concat.cast(this), '!');
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition startsWith(Field<T> value) {
|
||||
Field<String> concat = Factory.concat(
|
||||
escape(value.cast(String.class), '!'),
|
||||
Factory.literal("'%'"));
|
||||
|
||||
return like(concat.cast(this), '!');
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition endsWith(T value) {
|
||||
Field<String> concat = Factory.concat(
|
||||
Factory.literal("'%'"),
|
||||
Factory.val(escape("" + value, '!')));
|
||||
|
||||
return like(concat.cast(this), '!');
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition endsWith(Field<T> value) {
|
||||
Field<String> concat = Factory.concat(
|
||||
Factory.literal("'%'"),
|
||||
escape(value.cast(String.class), '!'));
|
||||
|
||||
return like(concat.cast(this), '!');
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition in(T... values) {
|
||||
return in(vals(values).toArray(new Field<?>[0]));
|
||||
|
||||
@ -1920,8 +1920,8 @@ public class Factory implements FactoryOperations {
|
||||
* @see Field#like(Field, char)
|
||||
*/
|
||||
@Support
|
||||
public static Field<String> escape(String value, char escape) {
|
||||
return val(value.replace("%", escape + "%").replace("_", escape + "_"));
|
||||
public static String escape(String value, char escape) {
|
||||
return value.replace("%", escape + "%").replace("_", escape + "_");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1935,7 +1935,12 @@ public class Factory implements FactoryOperations {
|
||||
*/
|
||||
@Support({ ASE, DB2, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE, SQLITE })
|
||||
public static Field<String> escape(Field<String> field, char escape) {
|
||||
return replace(replace(field, "%", escape + "%"), "_", escape + "_");
|
||||
Field<String> replace = field;
|
||||
|
||||
replace = replace(replace, literal("'%'"), literal("'" + escape + "%'"));
|
||||
replace = replace(replace, literal("'_'"), literal("'" + escape + "_'"));
|
||||
|
||||
return replace;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user