From 1b75820af0b7911c42d5a6dd3aec50e366d9479a Mon Sep 17 00:00:00 2001 From: Luc M Date: Sat, 4 Mar 2017 22:41:19 +0100 Subject: [PATCH] [5619] Add Field.containsIgnoreCase() to support Postgres' ILIKE operator --- jOOQ/src/main/java/org/jooq/Field.java | 46 +++++++++ .../java/org/jooq/impl/AbstractField.java | 20 ++++ .../org/jooq/impl/ContainsIgnoreCase.java | 99 +++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java diff --git a/jOOQ/src/main/java/org/jooq/Field.java b/jOOQ/src/main/java/org/jooq/Field.java index ce04847c69..421f24941c 100644 --- a/jOOQ/src/main/java/org/jooq/Field.java +++ b/jOOQ/src/main/java/org/jooq/Field.java @@ -1423,6 +1423,52 @@ public interface Field extends SelectField, GroupField, FieldOrRow { Condition notContains(Field value); /** + * Convenience method for {@link #likeIgnoreCase(String, char)} including proper + * adding of wildcards and escaping. + * + *

+ * This translates to this not ilike ('%' || escape(value, '\') || '%') escape '\' + * in {@link SQLDialect#POSTGRES}, or to + * lower(this) not like lower(('%' || escape(value, '\') || '%') escape '\') + * in all other dialects. + *

+ * + * @see DSL#escape(Field, char) + * @see #likeIgnoreCase(Field, char) + */ + @Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) + Condition containsIgnoreCase(T value); + + /** + * Convenience method for {@link #likeIgnoreCase(String, char)} including proper + * adding of wildcards and escaping. + * + *

+ * This translates to this not ilike ('%' || escape(value, '\') || '%') escape '\' + * in {@link SQLDialect#POSTGRES}, or to + * lower(this) not like lower(('%' || escape(value, '\') || '%') escape '\') + * in all other dialects. + *

+ * + * @see DSL#escape(Field, char) + * @see #likeIgnoreCase(Field, char) + */ + @Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) + Condition containsIgnoreCase(Field value); + + /** + * Inverse of {@link #containsIgnoreCase(Object)} + */ + @Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) + Condition notContainsIgnoreCase(T value); + + /** + * Inverse of {@link #containsIgnoreCase(Field)} + */ + @Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) + Condition notContainsIgnoreCase(Field value); + + /** * Convenience method for {@link #like(String, char)} including proper * adding of wildcards and escaping. *

diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java index 941d4f5ff8..492d8096ef 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java @@ -835,6 +835,26 @@ abstract class AbstractField extends AbstractQueryPart implements Field { return contains(value).not(); } + @Override + public final Condition containsIgnoreCase(T value) { + return new ContainsIgnoreCase<>(this, value); + } + + @Override + public final Condition containsIgnoreCase(Field value) { + return new ContainsIgnoreCase<>(this, value); + } + + @Override + public final Condition notContainsIgnoreCase(T value) { + return containsIgnoreCase(value).not(); + } + + @Override + public final Condition notContainsIgnoreCase(Field value) { + return containsIgnoreCase(value).not(); + } + @Override public final Condition startsWith(T value) { Field concat = DSL.concat(Tools.escapeForLike(value), inline("%")); diff --git a/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java b/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java new file mode 100644 index 0000000000..b6c7d44ce9 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java @@ -0,0 +1,99 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import static org.jooq.Clause.CONDITION; +import static org.jooq.Clause.CONDITION_COMPARISON; +import static org.jooq.impl.DSL.inline; + +import org.jooq.Clause; +import org.jooq.Condition; +import org.jooq.Configuration; +import org.jooq.Context; +import org.jooq.Field; + +/** + * Abstraction for various "containsIgnoreCase" operations + * + * @author lmarchau + */ +final class ContainsIgnoreCase extends AbstractCondition { + + /** + * Generated UID + */ + private static final long serialVersionUID = 1795491010886118843L; + + private static final Clause[] CLAUSES = {CONDITION, CONDITION_COMPARISON}; + + private final Field lhs; + private final Field rhs; + private final T value; + + ContainsIgnoreCase(Field field, T value) { + this.lhs = field; + this.rhs = null; + this.value = value; + } + + ContainsIgnoreCase(Field field, Field rhs) { + this.lhs = field; + this.rhs = rhs; + this.value = null; + } + + @Override + public final void accept(Context ctx) { + ctx.visit(condition(ctx.configuration())); + } + + @Override + public final Clause[] clauses(Context ctx) { + return CLAUSES; + } + + private final Condition condition(Configuration configuration) { + + Field concat; + + if (rhs == null) { + concat = DSL.concat(inline("%"), Tools.escapeForLike(value, configuration), inline("%")); + } else { + concat = DSL.concat(inline("%"), Tools.escapeForLike(rhs, configuration), inline("%")); + } + + return lhs.likeIgnoreCase(concat, Tools.ESCAPE); + } +}