From 5cd584787e031c8adfc724617734c9e48e0419ed Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 17 Feb 2012 10:20:05 +0000 Subject: [PATCH] [#1159] Support matching numbers with LIKE, e.g. ID LIKE '%33%' --- .../jooq/test/_/testcases/PredicateTests.java | 25 ++++++++++ jOOQ/src/main/java/org/jooq/Field.java | 16 +++---- .../java/org/jooq/impl/AbstractField.java | 48 +++++++++---------- .../java/org/jooq/impl/CompareCondition.java | 37 ++++++++++---- 4 files changed, 85 insertions(+), 41 deletions(-) diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/PredicateTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/PredicateTests.java index dfae28a4cc..8895ed72e4 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/PredicateTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/PredicateTests.java @@ -168,6 +168,7 @@ extends BaseTest extends NamedTypeProviderQueryPart, AliasProviderthis like value */ @Support - Condition like(Field value); + Condition like(Field value); /** * Create a condition to pattern-check this field against a value @@ -425,7 +425,7 @@ public interface Field extends NamedTypeProviderQueryPart, AliasProviderthis like value escape 'e' */ @Support - Condition like(Field value, char escape); + Condition like(Field value, char escape); /** * Create a condition to pattern-check this field against a value @@ -433,7 +433,7 @@ public interface Field extends NamedTypeProviderQueryPart, AliasProviderthis like value */ @Support - Condition like(T value); + Condition like(String value); /** * Create a condition to pattern-check this field against a value @@ -441,7 +441,7 @@ public interface Field extends NamedTypeProviderQueryPart, AliasProviderthis like value escape 'e' */ @Support - Condition like(T value, char escape); + Condition like(String value, char escape); /** * Create a condition to pattern-check this field against a value @@ -449,7 +449,7 @@ public interface Field extends NamedTypeProviderQueryPart, AliasProviderthis not like value */ @Support - Condition notLike(Field value); + Condition notLike(Field value); /** * Create a condition to pattern-check this field against a value @@ -457,7 +457,7 @@ public interface Field extends NamedTypeProviderQueryPart, AliasProviderthis not like value escape 'e' */ @Support - Condition notLike(Field value, char escape); + Condition notLike(Field value, char escape); /** * Create a condition to pattern-check this field against a value @@ -465,7 +465,7 @@ public interface Field extends NamedTypeProviderQueryPart, AliasProviderthis not like value */ @Support - Condition notLike(T value); + Condition notLike(String value); /** * Create a condition to pattern-check this field against a value @@ -473,7 +473,7 @@ public interface Field extends NamedTypeProviderQueryPart, AliasProviderthis not like value escape 'e' */ @Support - Condition notLike(T value, char escape); + Condition notLike(String value, char escape); /** * Convenience method for {@link #like(Object, char)} including proper diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java index d265b1235d..9f03d18a34 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java @@ -340,43 +340,43 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im } @Override - public final Condition like(T value) { + public final Condition like(String value) { return like(val(value)); } @Override - public final Condition like(T value, char escape) { + public final Condition like(String value, char escape) { return like(val(value), escape); } @Override - public final Condition like(Field value) { - return new CompareCondition(this, nullSafe(value), Comparator.LIKE); + 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); + public final Condition like(Field value, char escape) { + return new CompareCondition(this, nullSafe(value), Comparator.LIKE, escape); } @Override - public final Condition notLike(T value) { + public final Condition notLike(String value) { return notLike(val(value)); } @Override - public final Condition notLike(T value, char escape) { + public final Condition notLike(String value, char escape) { return notLike(val(value), escape); } @Override - public final Condition notLike(Field value) { - return new CompareCondition(this, nullSafe(value), Comparator.NOT_LIKE); + 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); + public final Condition notLike(Field value, char escape) { + return new CompareCondition(this, nullSafe(value), Comparator.NOT_LIKE, escape); } @Override @@ -386,7 +386,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im Factory.val(escape("" + value, '!')), Factory.literal("'%'")); - return like(concat.cast(this), '!'); + return like(concat, '!'); } @Override @@ -396,7 +396,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im escape(value.cast(String.class), '!'), Factory.literal("'%'")); - return like(concat.cast(this), '!'); + return like(concat, '!'); } @Override @@ -405,7 +405,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im Factory.val(escape("" + value, '!')), Factory.literal("'%'")); - return like(concat.cast(this), '!'); + return like(concat, '!'); } @Override @@ -414,7 +414,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im escape(value.cast(String.class), '!'), Factory.literal("'%'")); - return like(concat.cast(this), '!'); + return like(concat, '!'); } @Override @@ -423,7 +423,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im Factory.literal("'%'"), Factory.val(escape("" + value, '!'))); - return like(concat.cast(this), '!'); + return like(concat, '!'); } @Override @@ -432,7 +432,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im Factory.literal("'%'"), escape(value.cast(String.class), '!')); - return like(concat.cast(this), '!'); + return like(concat, '!'); } @Override @@ -525,7 +525,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im @Override public final Condition equal(Field field) { - return new CompareCondition(this, nullSafe(field), Comparator.EQUALS); + return new CompareCondition(this, nullSafe(field), Comparator.EQUALS); } @Override @@ -576,7 +576,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im @Override public final Condition notEqual(Field field) { - return new CompareCondition(this, nullSafe(field), Comparator.NOT_EQUALS); + return new CompareCondition(this, nullSafe(field), Comparator.NOT_EQUALS); } @Override @@ -627,7 +627,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im @Override public final Condition lessThan(Field field) { - return new CompareCondition(this, nullSafe(field), Comparator.LESS); + return new CompareCondition(this, nullSafe(field), Comparator.LESS); } @Override @@ -678,7 +678,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im @Override public final Condition lessOrEqual(Field field) { - return new CompareCondition(this, nullSafe(field), Comparator.LESS_OR_EQUAL); + return new CompareCondition(this, nullSafe(field), Comparator.LESS_OR_EQUAL); } @Override @@ -729,7 +729,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im @Override public final Condition greaterThan(Field field) { - return new CompareCondition(this, nullSafe(field), Comparator.GREATER); + return new CompareCondition(this, nullSafe(field), Comparator.GREATER); } @Override @@ -780,7 +780,7 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im @Override public final Condition greaterOrEqual(Field field) { - return new CompareCondition(this, nullSafe(field), Comparator.GREATER_OR_EQUAL); + return new CompareCondition(this, nullSafe(field), Comparator.GREATER_OR_EQUAL); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java b/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java index 6009eecf23..93b3d3ecfd 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java @@ -38,8 +38,13 @@ package org.jooq.impl; import static java.util.Arrays.asList; import static org.jooq.Comparator.EQUALS; +import static org.jooq.Comparator.LIKE; import static org.jooq.Comparator.NOT_EQUALS; +import static org.jooq.Comparator.NOT_LIKE; +import static org.jooq.SQLDialect.ASE; import static org.jooq.SQLDialect.DB2; +import static org.jooq.SQLDialect.DERBY; +import static org.jooq.SQLDialect.POSTGRES; import java.util.List; @@ -48,24 +53,25 @@ import org.jooq.BindContext; import org.jooq.Comparator; import org.jooq.Field; import org.jooq.RenderContext; +import org.jooq.SQLDialect; /** * @author Lukas Eder */ -class CompareCondition extends AbstractCondition { +class CompareCondition extends AbstractCondition { private static final long serialVersionUID = -747240442279619486L; - private final Field field1; - private final Field field2; + private final Field field1; + private final Field field2; private final Comparator comparator; private final Character escape; - CompareCondition(Field field1, Field field2, Comparator comparator) { + CompareCondition(Field field1, Field field2, Comparator comparator) { this(field1, field2, comparator, null); } - CompareCondition(Field field1, Field field2, Comparator comparator, Character escape) { + CompareCondition(Field field1, Field field2, Comparator comparator, Character escape) { this.field1 = field1; this.field2 = field2; this.comparator = comparator; @@ -89,7 +95,20 @@ class CompareCondition extends AbstractCondition { @Override public final void toSQL(RenderContext context) { - context.sql(field1) + SQLDialect dialect = context.getDialect(); + Field lhs = field1; + + // [#1159] Some dialects cannot auto-convert the LHS operand to a + // VARCHAR when applying a LIKE predicate + // [#293] TODO: This could apply to other operators, too + if ((comparator == LIKE || comparator == NOT_LIKE) + && field1.getType() != String.class + && asList(ASE, DERBY, POSTGRES).contains(dialect)) { + + lhs = lhs.cast(String.class); + } + + context.sql(lhs) .sql(" "); if (field2.isNullLiteral()) { @@ -107,13 +126,13 @@ class CompareCondition extends AbstractCondition { // [#1131] Some weird DB2 issue stops "LIKE" from working with a // concatenated search expression, if the expression is more than 4000 // characters long - boolean cast = context.getDialect() == DB2 && field2 instanceof Concat; + boolean castRhs = (dialect == DB2 && field2 instanceof Concat); context.sql(comparator.toSQL()) .sql(" ") - .sql(cast ? "cast(" : "") + .sql(castRhs ? "cast(" : "") .sql(field2) - .sql(cast ? " as varchar(4000))" : ""); + .sql(castRhs ? " as varchar(4000))" : ""); if (escape != null) { context.sql(" escape '")