From 5115e356f9eb671bbaee0d1f8f0f5ec45afe9d49 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 27 Jan 2012 09:27:56 +0000 Subject: [PATCH] [#1072] Add support for LIKE .. ESCAPE .. syntax --- .../src/org/jooq/test/jOOQAbstractTest.java | 21 +++ jOOQ/src/main/java/org/jooq/Field.java | 128 +++++++++++++++--- .../java/org/jooq/impl/AbstractField.java | 20 +++ .../java/org/jooq/impl/CompareCondition.java | 12 ++ .../src/test/java/org/jooq/test/jOOQTest.java | 19 +++ 5 files changed, 184 insertions(+), 16 deletions(-) diff --git a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java index 16b2a716fe..2420e57bb0 100644 --- a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java +++ b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java @@ -8179,6 +8179,8 @@ public abstract class jOOQAbstractTest< @Test public void testLike() throws Exception { + reset = false; + Field 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) 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 diff --git a/jOOQ/src/main/java/org/jooq/Field.java b/jOOQ/src/main/java/org/jooq/Field.java index a3625e5528..3971cb7cfd 100644 --- a/jOOQ/src/main/java/org/jooq/Field.java +++ b/jOOQ/src/main/java/org/jooq/Field.java @@ -376,109 +376,205 @@ public interface Field extends NamedTypeProviderQueryPart, AliasProviderthis is null + * Create a condition to check this field against null. + *

+ * SQL: this is null */ @Support Condition isNull(); /** - * this is not null + * Create a condition to check this field against null. + *

+ * SQL: this is not null */ @Support Condition isNotNull(); /** + * Create a condition to check this field known string literals for + * true + *

+ * SQL: * lcase(this) in ("1", "y", "yes", "true", "on", "enabled") */ @Support Condition isTrue(); /** + * Create a condition to check this field known string literals for + * false + *

+ * SQL: * lcase(this) in ("0", "n", "no", "false", "off", "disabled") */ @Support Condition isFalse(); /** - * this like value + * Create a condition to pattern-check this field against a value + *

+ * SQL: this like value */ @Support Condition like(Field value); /** - * this like value + * Create a condition to pattern-check this field against a value + *

+ * SQL: this like value escape 'e' + */ + @Support + Condition like(Field value, char escape); + + /** + * Create a condition to pattern-check this field against a value + *

+ * SQL: this like value */ @Support Condition like(T value); /** - * this not like value + * Create a condition to pattern-check this field against a value + *

+ * SQL: this like value escape 'e' + */ + @Support + Condition like(T value, char escape); + + /** + * Create a condition to pattern-check this field against a value + *

+ * SQL: this not like value */ @Support Condition notLike(Field value); /** - * this not like value + * Create a condition to pattern-check this field against a value + *

+ * SQL: this not like value escape 'e' + */ + @Support + Condition notLike(Field value, char escape); + + /** + * Create a condition to pattern-check this field against a value + *

+ * SQL: this not like value */ @Support Condition notLike(T value); /** - * this in (values...) + * Create a condition to pattern-check this field against a value + *

+ * SQL: this not like value escape 'e' + */ + @Support + Condition notLike(T value, char escape); + + /** + * Create a condition to check this field against several values + *

+ * SQL: this in (values...) */ @Support Condition in(Collection values); /** - * this in (values...) + * Create a condition to check this field against several values + *

+ * SQL: this in (values...) */ @Support Condition in(T... values); /** - * this in (values...) + * Create a condition to check this field against several values + *

+ * SQL: this in (values...) */ @Support Condition in(Field... values); /** - * this in (select...) + * Create a condition to check this field against a subquery + *

+ * 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. + *

+ * SQL: this in (select...) */ @Support Condition in(Select query); /** - * this not in (values...) + * Create a condition to check this field against several values + *

+ * Note that if any of the passed values is NULL, then the + * condition will be NULL (or false, depending on + * the dialect) as well. This is standard SQL behaviour. + *

+ * SQL: this not in (values...) */ @Support Condition notIn(Collection values); /** - * this not in (values...) + * Create a condition to check this field against several values + *

+ * Note that if any of the passed values is NULL, then the + * condition will be NULL (or false, depending on + * the dialect) as well. This is standard SQL behaviour. + *

+ * SQL: this not in (values...) */ @Support Condition notIn(T... values); /** - * this not in (values...) + * Create a condition to check this field against several values + *

+ * Note that if any of the passed values is NULL, then the + * condition will be NULL (or false, depending on + * the dialect) as well. This is standard SQL behaviour. + *

+ * SQL: this not in (values...) */ @Support Condition notIn(Field... values); /** - * this not in (select...) + * Create a condition to check this field against a subquery + *

+ * 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. + *

+ * Note that if any of the passed values is NULL, then the + * condition will be NULL (or false, depending on + * the dialect) as well. This is standard SQL behaviour. + *

+ * SQL: this not in (select...) */ @Support Condition notIn(Select query); /** - * this between minValue and maxValue + * Create a condition to check this field against some bounds + *

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

+ * SQL: this between minValue and maxValue */ @Support Condition between(Field minValue, Field maxValue); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java index f533e003d5..deb3dc42f6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java @@ -343,21 +343,41 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart 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 value) { return new CompareCondition(this, nullSafe(value), Comparator.LIKE); } + @Override + public final Condition like(Field value, char escape) { + return new CompareCondition(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 value) { return new CompareCondition(this, nullSafe(value), Comparator.NOT_LIKE); } + @Override + public final Condition notLike(Field value, char escape) { + return new CompareCondition(this, nullSafe(value), Comparator.NOT_LIKE, escape); + } + @Override public final Condition in(T... values) { return in(vals(values).toArray(new Field[0])); diff --git a/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java b/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java index 031c17a995..936d78162f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java @@ -54,11 +54,17 @@ class CompareCondition extends AbstractCondition { private final Field field1; private final Field field2; private final Comparator comparator; + private final Character escape; CompareCondition(Field field1, Field field2, Comparator comparator) { + this(field1, field2, comparator, null); + } + + CompareCondition(Field field1, Field field2, Comparator comparator, Character escape) { this.field1 = field1; this.field2 = field2; this.comparator = comparator; + this.escape = escape; } @Override @@ -91,5 +97,11 @@ class CompareCondition extends AbstractCondition { context.sql(comparator.toSQL()) .sql(" ") .sql(field2); + + if (escape != null) { + context.sql(" escape '") + .sql(escape) + .sql("'"); + } } } diff --git a/jOOQ/src/test/java/org/jooq/test/jOOQTest.java b/jOOQ/src/test/java/org/jooq/test/jOOQTest.java index 1c66e081ce..2a1809ca3b 100644 --- a/jOOQ/src/test/java/org/jooq/test/jOOQTest.java +++ b/jOOQ/src/test/java/org/jooq/test/jOOQTest.java @@ -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");