[#1072] Add support for LIKE .. ESCAPE .. syntax
This commit is contained in:
parent
23a26069f2
commit
5115e356f9
@ -8179,6 +8179,8 @@ public abstract class jOOQAbstractTest<
|
||||
|
||||
@Test
|
||||
public void testLike() throws Exception {
|
||||
reset = false;
|
||||
|
||||
Field<String> notLike = TBook_PUBLISHED_IN().cast(String.class);
|
||||
|
||||
// DB2 doesn't support this syntax
|
||||
@ -8193,6 +8195,25 @@ public abstract class jOOQAbstractTest<
|
||||
.fetch();
|
||||
|
||||
assertEquals(3, books.size());
|
||||
|
||||
assertEquals(1,
|
||||
create().insertInto(TBook())
|
||||
.set(TBook_ID(), 5)
|
||||
.set(TBook_AUTHOR_ID(), 2)
|
||||
.set(TBook_PUBLISHED_IN(), 2012)
|
||||
.set((Field<Integer>) TBook_LANGUAGE_ID(), 1)
|
||||
.set(TBook_TITLE(), "About percentages (%) and underscores (_), a critical review")
|
||||
.execute());
|
||||
|
||||
// [#1072] Add checks for ESCAPE syntax
|
||||
books =
|
||||
create().selectFrom(TBook())
|
||||
.where(TBook_TITLE().like("%(!%)%", '!'))
|
||||
.and(TBook_TITLE().like("%(#_)%", '#'))
|
||||
.and(TBook_TITLE().notLike("%(!%)%", '#'))
|
||||
.and(TBook_TITLE().notLike("%(#_)%", '!'))
|
||||
.fetch();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -376,109 +376,205 @@ public interface Field<T> extends NamedTypeProviderQueryPart<T>, AliasProvider<F
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* <code>this is null</code>
|
||||
* Create a condition to check this field against <code>null</code>.
|
||||
* <p>
|
||||
* SQL: <code>this is null</code>
|
||||
*/
|
||||
@Support
|
||||
Condition isNull();
|
||||
|
||||
/**
|
||||
* <code>this is not null</code>
|
||||
* Create a condition to check this field against <code>null</code>.
|
||||
* <p>
|
||||
* SQL: <code>this is not null</code>
|
||||
*/
|
||||
@Support
|
||||
Condition isNotNull();
|
||||
|
||||
/**
|
||||
* Create a condition to check this field known string literals for
|
||||
* <code>true</code>
|
||||
* <p>
|
||||
* SQL:
|
||||
* <code>lcase(this) in ("1", "y", "yes", "true", "on", "enabled")</code>
|
||||
*/
|
||||
@Support
|
||||
Condition isTrue();
|
||||
|
||||
/**
|
||||
* Create a condition to check this field known string literals for
|
||||
* <code>false</code>
|
||||
* <p>
|
||||
* SQL:
|
||||
* <code>lcase(this) in ("0", "n", "no", "false", "off", "disabled")</code>
|
||||
*/
|
||||
@Support
|
||||
Condition isFalse();
|
||||
|
||||
/**
|
||||
* <code>this like value</code>
|
||||
* Create a condition to pattern-check this field against a value
|
||||
* <p>
|
||||
* SQL: <code>this like value</code>
|
||||
*/
|
||||
@Support
|
||||
Condition like(Field<T> value);
|
||||
|
||||
/**
|
||||
* <code>this like value</code>
|
||||
* Create a condition to pattern-check this field against a value
|
||||
* <p>
|
||||
* SQL: <code>this like value escape 'e'</code>
|
||||
*/
|
||||
@Support
|
||||
Condition like(Field<T> value, char escape);
|
||||
|
||||
/**
|
||||
* Create a condition to pattern-check this field against a value
|
||||
* <p>
|
||||
* SQL: <code>this like value</code>
|
||||
*/
|
||||
@Support
|
||||
Condition like(T value);
|
||||
|
||||
/**
|
||||
* <code>this not like value</code>
|
||||
* Create a condition to pattern-check this field against a value
|
||||
* <p>
|
||||
* SQL: <code>this like value escape 'e'</code>
|
||||
*/
|
||||
@Support
|
||||
Condition like(T value, char escape);
|
||||
|
||||
/**
|
||||
* Create a condition to pattern-check this field against a value
|
||||
* <p>
|
||||
* SQL: <code>this not like value</code>
|
||||
*/
|
||||
@Support
|
||||
Condition notLike(Field<T> value);
|
||||
|
||||
/**
|
||||
* <code>this not like value</code>
|
||||
* Create a condition to pattern-check this field against a value
|
||||
* <p>
|
||||
* SQL: <code>this not like value escape 'e'</code>
|
||||
*/
|
||||
@Support
|
||||
Condition notLike(Field<T> value, char escape);
|
||||
|
||||
/**
|
||||
* Create a condition to pattern-check this field against a value
|
||||
* <p>
|
||||
* SQL: <code>this not like value</code>
|
||||
*/
|
||||
@Support
|
||||
Condition notLike(T value);
|
||||
|
||||
/**
|
||||
* <code>this in (values...)</code>
|
||||
* Create a condition to pattern-check this field against a value
|
||||
* <p>
|
||||
* SQL: <code>this not like value escape 'e'</code>
|
||||
*/
|
||||
@Support
|
||||
Condition notLike(T value, char escape);
|
||||
|
||||
/**
|
||||
* Create a condition to check this field against several values
|
||||
* <p>
|
||||
* SQL: <code>this in (values...)</code>
|
||||
*/
|
||||
@Support
|
||||
Condition in(Collection<T> values);
|
||||
|
||||
/**
|
||||
* <code>this in (values...)</code>
|
||||
* Create a condition to check this field against several values
|
||||
* <p>
|
||||
* SQL: <code>this in (values...)</code>
|
||||
*/
|
||||
@Support
|
||||
Condition in(T... values);
|
||||
|
||||
/**
|
||||
* <code>this in (values...)</code>
|
||||
* Create a condition to check this field against several values
|
||||
* <p>
|
||||
* SQL: <code>this in (values...)</code>
|
||||
*/
|
||||
@Support
|
||||
Condition in(Field<?>... values);
|
||||
|
||||
/**
|
||||
* <code>this in (select...)</code>
|
||||
* Create a condition to check this field against a subquery
|
||||
* <p>
|
||||
* Note that the subquery must return exactly one field. This is not checked
|
||||
* by jOOQ and will result in syntax errors on the database, if not used
|
||||
* correctly.
|
||||
* <p>
|
||||
* SQL: <code>this in (select...)</code>
|
||||
*/
|
||||
@Support
|
||||
Condition in(Select<?> query);
|
||||
|
||||
/**
|
||||
* <code>this not in (values...)</code>
|
||||
* Create a condition to check this field against several values
|
||||
* <p>
|
||||
* Note that if any of the passed values is <code>NULL</code>, then the
|
||||
* condition will be <code>NULL</code> (or <code>false</code>, depending on
|
||||
* the dialect) as well. This is standard SQL behaviour.
|
||||
* <p>
|
||||
* SQL: <code>this not in (values...)</code>
|
||||
*/
|
||||
@Support
|
||||
Condition notIn(Collection<T> values);
|
||||
|
||||
/**
|
||||
* <code>this not in (values...)</code>
|
||||
* Create a condition to check this field against several values
|
||||
* <p>
|
||||
* Note that if any of the passed values is <code>NULL</code>, then the
|
||||
* condition will be <code>NULL</code> (or <code>false</code>, depending on
|
||||
* the dialect) as well. This is standard SQL behaviour.
|
||||
* <p>
|
||||
* SQL: <code>this not in (values...)</code>
|
||||
*/
|
||||
@Support
|
||||
Condition notIn(T... values);
|
||||
|
||||
/**
|
||||
* <code>this not in (values...)</code>
|
||||
* Create a condition to check this field against several values
|
||||
* <p>
|
||||
* Note that if any of the passed values is <code>NULL</code>, then the
|
||||
* condition will be <code>NULL</code> (or <code>false</code>, depending on
|
||||
* the dialect) as well. This is standard SQL behaviour.
|
||||
* <p>
|
||||
* SQL: <code>this not in (values...)</code>
|
||||
*/
|
||||
@Support
|
||||
Condition notIn(Field<?>... values);
|
||||
|
||||
/**
|
||||
* <code>this not in (select...)</code>
|
||||
* Create a condition to check this field against a subquery
|
||||
* <p>
|
||||
* Note that the subquery must return exactly one field. This is not checked
|
||||
* by jOOQ and will result in syntax errors on the database, if not used
|
||||
* correctly.
|
||||
* <p>
|
||||
* Note that if any of the passed values is <code>NULL</code>, then the
|
||||
* condition will be <code>NULL</code> (or <code>false</code>, depending on
|
||||
* the dialect) as well. This is standard SQL behaviour.
|
||||
* <p>
|
||||
* SQL: <code>this not in (select...)</code>
|
||||
*/
|
||||
@Support
|
||||
Condition notIn(Select<?> query);
|
||||
|
||||
/**
|
||||
* <code>this between minValue and maxValue</code>
|
||||
* Create a condition to check this field against some bounds
|
||||
* <p>
|
||||
* SQL: <code>this between minValue and maxValue</code>
|
||||
*/
|
||||
@Support
|
||||
Condition between(T minValue, T maxValue);
|
||||
|
||||
/**
|
||||
* <code>this between minValue and maxValue</code>
|
||||
* Create a condition to check this field against some bounds
|
||||
* <p>
|
||||
* SQL: <code>this between minValue and maxValue</code>
|
||||
*/
|
||||
@Support
|
||||
Condition between(Field<T> minValue, Field<T> maxValue);
|
||||
|
||||
@ -343,21 +343,41 @@ abstract class AbstractField<T> extends AbstractNamedTypeProviderQueryPart<T> im
|
||||
return like(val(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition like(T value, char escape) {
|
||||
return like(val(value), escape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition like(Field<T> value) {
|
||||
return new CompareCondition<T>(this, nullSafe(value), Comparator.LIKE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition like(Field<T> value, char escape) {
|
||||
return new CompareCondition<T>(this, nullSafe(value), Comparator.LIKE, escape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition notLike(T value) {
|
||||
return notLike(val(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition notLike(T value, char escape) {
|
||||
return notLike(val(value), escape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition notLike(Field<T> value) {
|
||||
return new CompareCondition<T>(this, nullSafe(value), Comparator.NOT_LIKE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition notLike(Field<T> value, char escape) {
|
||||
return new CompareCondition<T>(this, nullSafe(value), Comparator.NOT_LIKE, escape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition in(T... values) {
|
||||
return in(vals(values).toArray(new Field<?>[0]));
|
||||
|
||||
@ -54,11 +54,17 @@ class CompareCondition<T> extends AbstractCondition {
|
||||
private final Field<T> field1;
|
||||
private final Field<T> field2;
|
||||
private final Comparator comparator;
|
||||
private final Character escape;
|
||||
|
||||
CompareCondition(Field<T> field1, Field<T> field2, Comparator comparator) {
|
||||
this(field1, field2, comparator, null);
|
||||
}
|
||||
|
||||
CompareCondition(Field<T> field1, Field<T> field2, Comparator comparator, Character escape) {
|
||||
this.field1 = field1;
|
||||
this.field2 = field2;
|
||||
this.comparator = comparator;
|
||||
this.escape = escape;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -91,5 +97,11 @@ class CompareCondition<T> extends AbstractCondition {
|
||||
context.sql(comparator.toSQL())
|
||||
.sql(" ")
|
||||
.sql(field2);
|
||||
|
||||
if (escape != null) {
|
||||
context.sql(" escape '")
|
||||
.sql(escape)
|
||||
.sql("'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -720,6 +720,25 @@ public class jOOQTest {
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLikeCondition() throws Exception {
|
||||
Condition c1 = FIELD_NAME1.like("%a%");
|
||||
assertEquals("\"TABLE1\".\"ID1\" like '%a%')", r_refI().render(c1));
|
||||
assertEquals("\"TABLE1\".\"ID1\" like ?)", r_ref().render(c1));
|
||||
|
||||
Condition c2 = FIELD_NAME1.notLike("%a%");
|
||||
assertEquals("\"TABLE1\".\"ID1\" not like '%a%')", r_refI().render(c2));
|
||||
assertEquals("\"TABLE1\".\"ID1\" not like ?)", r_ref().render(c2));
|
||||
|
||||
Condition c3 = FIELD_NAME1.like("%a%", '!');
|
||||
assertEquals("\"TABLE1\".\"ID1\" like '%a%' escape '!')", r_refI().render(c3));
|
||||
assertEquals("\"TABLE1\".\"ID1\" like ? escape '!')", r_ref().render(c3));
|
||||
|
||||
Condition c4 = FIELD_NAME1.notLike("%a%", '!');
|
||||
assertEquals("\"TABLE1\".\"ID1\" not like '%a%' escape '!')", r_refI().render(c4));
|
||||
assertEquals("\"TABLE1\".\"ID1\" not like ? escape '!')", r_ref().render(c4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlainSQLCondition() throws Exception {
|
||||
Condition c1 = condition("TABLE1.ID = 10");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user