diff --git a/jOOQ/src/main/java/org/jooq/Field.java b/jOOQ/src/main/java/org/jooq/Field.java index 8ecfe12a56..ee0852ddf0 100644 --- a/jOOQ/src/main/java/org/jooq/Field.java +++ b/jOOQ/src/main/java/org/jooq/Field.java @@ -1285,6 +1285,228 @@ extends @Support({ CUBRID, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE, YUGABYTE }) Field shr(Field count); + // ------------------------------------------------------------------------- + // String functions + // ------------------------------------------------------------------------- + + /** + * The CONTAINS operator. + *

+ * Convenience method for {@link #like(String, char)} including proper + * adding of wildcards and escaping. + *

+ * SQL: this like ('%' || escape(value, '\') || '%') escape '\' + *

+ * Note: This also works with numbers, for instance + * val(1133).contains(13) + *

+ * If you're using {@link SQLDialect#POSTGRES}, then you can use this method + * also to express the "ARRAY contains" operator. For example:

+     * // Use this expression
+     * val(new Integer[] { 1, 2, 3 }).contains(new Integer[] { 1, 2 })
+     * 
+     * // ... to render this SQL
+     * ARRAY[1, 2, 3] @> ARRAY[1, 2]
+     * 
+ *

+ * Note, this does not correspond to the Oracle Text CONTAINS() + * function. Refer to {@link OracleDSL#contains(Field, String)} instead. + * + * @param content is wrapped as {@link #val(Object)}. + */ + @NotNull + @Support + Condition contains(T content); + + /** + * The CONTAINS operator. + *

+ * Convenience method for {@link #like(String, char)} including proper + * adding of wildcards and escaping. + *

+ * SQL: this like ('%' || escape(value, '\') || '%') escape '\' + *

+ * Note: This also works with numbers, for instance + * val(1133).contains(13) + *

+ * If you're using {@link SQLDialect#POSTGRES}, then you can use this method + * also to express the "ARRAY contains" operator. For example:

+     * // Use this expression
+     * val(new Integer[] { 1, 2, 3 }).contains(new Integer[] { 1, 2 })
+     * 
+     * // ... to render this SQL
+     * ARRAY[1, 2, 3] @> ARRAY[1, 2]
+     * 
+ *

+ * Note, this does not correspond to the Oracle Text CONTAINS() + * function. Refer to {@link OracleDSL#contains(Field, String)} instead. + */ + @NotNull + @Support + Condition contains(Field content); + + /** + * The CONTAINS_IGNORE_CASE operator. + *

+ * Convenience method for {@link #likeIgnoreCase(String, char)} including + * proper adding of wildcards and escaping. + *

+ * This translates to + * this ilike ('%' || escape(value, '\') || '%') escape '\' in + * {@link SQLDialect#POSTGRES}, or to + * lower(this) not like lower(('%' || escape(value, '\') || '%') escape '\') + * in all other dialects. + * + * @param content is wrapped as {@link #val(Object)}. + */ + @NotNull + @Support + Condition containsIgnoreCase(T content); + + /** + * The CONTAINS_IGNORE_CASE operator. + *

+ * Convenience method for {@link #likeIgnoreCase(String, char)} including + * proper adding of wildcards and escaping. + *

+ * This translates to + * this ilike ('%' || escape(value, '\') || '%') escape '\' in + * {@link SQLDialect#POSTGRES}, or to + * lower(this) not like lower(('%' || escape(value, '\') || '%') escape '\') + * in all other dialects. + */ + @NotNull + @Support + Condition containsIgnoreCase(Field content); + + /** + * The ENDS_WITH operator. + *

+ * Convenience method for {@link #like(String, char)} including proper + * adding of wildcards and escaping. + *

+ * SQL: this like ('%' || escape(value, '\')) escape '\' + *

+ * Note: This also works with numbers, for instance + * val(1133).endsWith(33) + * + * @param suffix is wrapped as {@link #val(Object)}. + */ + @NotNull + @Support + Condition endsWith(T suffix); + + /** + * The ENDS_WITH operator. + *

+ * Convenience method for {@link #like(String, char)} including proper + * adding of wildcards and escaping. + *

+ * SQL: this like ('%' || escape(value, '\')) escape '\' + *

+ * Note: This also works with numbers, for instance + * val(1133).endsWith(33) + */ + @NotNull + @Support + Condition endsWith(Field suffix); + + /** + * The ENDS_WITH_IGNORE_CASE operator. + *

+ * Convenience method for {@link #like(String, char)} including proper + * adding of wildcards and escaping. + *

+ * SQL: lower(this) like ('%' || lower(escape(value, '\'))) escape '\' + *

+ * Note: This also works with numbers, for instance + * val(1133).endsWithIgnoreCase(33) + * + * @param suffix is wrapped as {@link #val(Object)}. + */ + @NotNull + @Support + Condition endsWithIgnoreCase(T suffix); + + /** + * The ENDS_WITH_IGNORE_CASE operator. + *

+ * Convenience method for {@link #like(String, char)} including proper + * adding of wildcards and escaping. + *

+ * SQL: lower(this) like ('%' || lower(escape(value, '\'))) escape '\' + *

+ * Note: This also works with numbers, for instance + * val(1133).endsWithIgnoreCase(33) + */ + @NotNull + @Support + Condition endsWithIgnoreCase(Field suffix); + + /** + * The STARTS_WITH operator. + *

+ * Convenience method for {@link #like(String, char)} including proper + * adding of wildcards and escaping. + *

+ * SQL: this like (escape(value, '\') || '%') escape '\' + *

+ * Note: This also works with numbers, for instance + * val(1133).startsWith(11) + * + * @param prefix is wrapped as {@link #val(Object)}. + */ + @NotNull + @Support + Condition startsWith(T prefix); + + /** + * The STARTS_WITH operator. + *

+ * Convenience method for {@link #like(String, char)} including proper + * adding of wildcards and escaping. + *

+ * SQL: this like (escape(value, '\') || '%') escape '\' + *

+ * Note: This also works with numbers, for instance + * val(1133).startsWith(11) + */ + @NotNull + @Support + Condition startsWith(Field prefix); + + /** + * The STARTS_WITH_IGNORE_CASE operator. + *

+ * Convenience method for {@link #like(String, char)} including proper + * adding of wildcards and escaping. + *

+ * SQL: lower(this) like (lower(escape(value, '\')) || '%') escape '\' + *

+ * Note: This also works with numbers, for instance + * val(1133).startsWithIgnoreCase(11) + * + * @param prefix is wrapped as {@link #val(Object)}. + */ + @NotNull + @Support + Condition startsWithIgnoreCase(T prefix); + + /** + * The STARTS_WITH_IGNORE_CASE operator. + *

+ * Convenience method for {@link #like(String, char)} including proper + * adding of wildcards and escaping. + *

+ * SQL: lower(this) like (lower(escape(value, '\')) || '%') escape '\' + *

+ * Note: This also works with numbers, for instance + * val(1133).startsWithIgnoreCase(11) + */ + @NotNull + @Support + Condition startsWithIgnoreCase(Field prefix); + @@ -2081,62 +2303,6 @@ extends @Support Condition notLikeIgnoreCase(String value, char escape); - /** - * Convenience method for {@link #like(String, char)} including proper - * adding of wildcards and escaping. - *

- * SQL: this like ('%' || escape(value, '\') || '%') escape '\' - *

- * Note: This also works with numbers, for instance - * val(1133).contains(13) - *

- * If you're using {@link SQLDialect#POSTGRES}, then you can use this method - * also to express the "ARRAY contains" operator. For example:

-     * // Use this expression
-     * val(new Integer[] { 1, 2, 3 }).contains(new Integer[] { 1, 2 })
-     *
-     * // ... to render this SQL
-     * ARRAY[1, 2, 3] @> ARRAY[1, 2]
-     * 
- *

- * Note, this does not correspond to the Oracle Text CONTAINS() - * function. Refer to {@link OracleDSL#contains(Field, String)} instead. - * - * @see DSL#escape(String, char) - * @see #like(String, char) - */ - @NotNull - @Support - Condition contains(T value); - - /** - * Convenience method for {@link #like(String, char)} including proper - * adding of wildcards and escaping. - *

- * SQL: this like ('%' || escape(value, '\') || '%') escape '\' - *

- * Note: This also works with numbers, for instance - * val(1133).contains(13) - *

- * If you're using {@link SQLDialect#POSTGRES}, then you can use this method - * also to express the "ARRAY contains" operator. For example:

-     * // Use this expression
-     * val(new Integer[] { 1, 2, 3 }).contains(new Integer[] { 1, 2 })
-     *
-     * // ... to render this SQL
-     * ARRAY[1, 2, 3] @> ARRAY[1, 2]
-     * 
- *

- * Note, this does not correspond to the Oracle Text CONTAINS() - * function. Refer to {@link OracleDSL#contains(Field, String)} instead. - * - * @see DSL#escape(Field, char) - * @see #like(Field, char) - */ - @NotNull - @Support({ CUBRID, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, YUGABYTE }) - Condition contains(Field value); - /** * Inverse of {@link #contains(Object)}. */ @@ -2151,44 +2317,6 @@ extends @Support({ CUBRID, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, YUGABYTE }) Condition notContains(Field value); - /** - * Convenience method for {@link #likeIgnoreCase(String, char)} including - * proper adding of wildcards and escaping. - *

- * This translates to - * this 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(String, char) - * @see #contains(Object) - */ - @NotNull - @Support({ CUBRID, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, YUGABYTE }) - Condition containsIgnoreCase(T value); - - /** - * Convenience method for {@link #likeIgnoreCase(String, char)} including - * proper adding of wildcards and escaping. - *

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

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

- * SQL: this like (escape(value, '\') || '%') escape '\' - *

- * Note: This also works with numbers, for instance - * val(1133).startsWith(11) - * - * @see DSL#escape(String, char) - * @see #like(String, char) - */ - @NotNull - @Support - Condition startsWith(T value); - - /** - * Convenience method for {@link #like(String, char)} including proper - * adding of wildcards and escaping. - *

- * SQL: this like (escape(value, '\') || '%') escape '\' - *

- * Note: This also works with numbers, for instance - * val(1133).startsWith(11) - * - * @see DSL#escape(Field, char) - * @see #like(Field, char) - */ - @NotNull - @Support({ CUBRID, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, YUGABYTE }) - Condition startsWith(Field value); - - /** - * Convenience method for {@link #like(String, char)} including proper - * adding of wildcards and escaping. - *

- * SQL: lower(this) like (lower(escape(value, '\')) || '%') escape '\' - *

- * Note: This also works with numbers, for instance - * val(1133).startsWithIgnoreCase(11) - * - * @see DSL#escape(String, char) - * @see #like(String, char) - */ - @NotNull - @Support - Condition startsWithIgnoreCase(T value); - - /** - * Convenience method for {@link #like(String, char)} including proper - * adding of wildcards and escaping. - *

- * SQL: lower(this) like (lower(escape(value, '\')) || '%') escape '\' - *

- * Note: This also works with numbers, for instance - * val(1133).startsWithIgnoreCase(11) - * - * @see DSL#escape(Field, char) - * @see #like(Field, char) - */ - @NotNull - @Support({ CUBRID, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, YUGABYTE }) - Condition startsWithIgnoreCase(Field value); - - /** - * Convenience method for {@link #like(String, char)} including proper - * adding of wildcards and escaping. - *

- * SQL: this like ('%' || escape(value, '\')) escape '\' - *

- * Note: This also works with numbers, for instance - * val(1133).endsWith(33) - * - * @see DSL#escape(String, char) - * @see #like(String, char) - */ - @NotNull - @Support - Condition endsWith(T value); - - /** - * Convenience method for {@link #like(String, char)} including proper - * adding of wildcards and escaping. - *

- * SQL: this like ('%' || escape(value, '\')) escape '\' - *

- * Note: This also works with numbers, for instance - * val(1133).endsWith(33) - * - * @see DSL#escape(Field, char) - * @see #like(Field, char) - */ - @NotNull - @Support({ CUBRID, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, YUGABYTE }) - Condition endsWith(Field value); - - /** - * Convenience method for {@link #like(String, char)} including proper - * adding of wildcards and escaping. - *

- * SQL: lower(this) like ('%' || lower(escape(value, '\'))) escape '\' - *

- * Note: This also works with numbers, for instance - * val(1133).endsWithIgnoreCase(33) - * - * @see DSL#escape(String, char) - * @see #like(String, char) - */ - @NotNull - @Support - Condition endsWithIgnoreCase(T value); - - /** - * Convenience method for {@link #like(String, char)} including proper - * adding of wildcards and escaping. - *

- * SQL: this like ('%' || lower(escape(value, '\'))) escape '\' - *

- * Note: This also works with numbers, for instance - * val(1133).endsWithIgnoreCase(33) - * - * @see DSL#escape(Field, char) - * @see #like(Field, char) - */ - @NotNull - @Support({ CUBRID, FIREBIRD, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, YUGABYTE }) - Condition endsWithIgnoreCase(Field value); - // ------------------------------------------------------------------------ // IN predicates // ------------------------------------------------------------------------ diff --git a/jOOQ/src/main/java/org/jooq/Table.java b/jOOQ/src/main/java/org/jooq/Table.java index 0ee64cb332..cbabbce668 100644 --- a/jOOQ/src/main/java/org/jooq/Table.java +++ b/jOOQ/src/main/java/org/jooq/Table.java @@ -2445,7 +2445,7 @@ public interface Table extends TableLike, RecordQualifier *

diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java index d7f5adf28a..0db58d09e2 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java @@ -770,6 +770,82 @@ abstract class AbstractField extends AbstractTypedNamed implements Field content) { + return new Contains(this, nullSafe(content, getDataType())); + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Condition containsIgnoreCase(T content) { + return new ContainsIgnoreCase(this, Tools.field(content, this)); + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Condition containsIgnoreCase(Field content) { + return new ContainsIgnoreCase(this, nullSafe(content, getDataType())); + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Condition endsWith(T suffix) { + return new EndsWith(this, Tools.field(suffix, this)); + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Condition endsWith(Field suffix) { + return new EndsWith(this, nullSafe(suffix, getDataType())); + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Condition endsWithIgnoreCase(T suffix) { + return new EndsWithIgnoreCase(this, Tools.field(suffix, this)); + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Condition endsWithIgnoreCase(Field suffix) { + return new EndsWithIgnoreCase(this, nullSafe(suffix, getDataType())); + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Condition startsWith(T prefix) { + return new StartsWith(this, Tools.field(prefix, this)); + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Condition startsWith(Field prefix) { + return new StartsWith(this, nullSafe(prefix, getDataType())); + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Condition startsWithIgnoreCase(T prefix) { + return new StartsWithIgnoreCase(this, Tools.field(prefix, this)); + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Condition startsWithIgnoreCase(Field prefix) { + return new StartsWithIgnoreCase(this, nullSafe(prefix, getDataType())); + } + @@ -1101,20 +1177,6 @@ abstract class AbstractField extends AbstractTypedNamed implements Field(this, value, true, true); - } - - @Override - public final Condition contains(Field value) { - return new Contains<>(this, value, true, true); - } - @Override public final Condition notContains(T value) { return contains(value).not(); @@ -1125,16 +1187,6 @@ abstract class AbstractField extends AbstractTypedNamed implements Field value) { - return new ContainsIgnoreCase(this, value, true, true); - } - @Override public final Condition notContainsIgnoreCase(T value) { return containsIgnoreCase(value).not(); @@ -1145,46 +1197,6 @@ abstract class AbstractField extends AbstractTypedNamed implements Field value) { - return new Contains<>(this, value, false, true); - } - - @Override - public final Condition startsWithIgnoreCase(T value) { - return startsWithIgnoreCase(Tools.field(value, this)); - } - - @Override - public final Condition startsWithIgnoreCase(Field value) { - return new ContainsIgnoreCase(this, value, false, true); - } - - @Override - public final Condition endsWith(T value) { - return endsWith(Tools.field(value, this)); - } - - @Override - public final Condition endsWith(Field value) { - return new Contains<>(this, value, true, false); - } - - @Override - public final Condition endsWithIgnoreCase(T value) { - return endsWithIgnoreCase(Tools.field(value, this)); - } - - @Override - public final Condition endsWithIgnoreCase(Field value) { - return new ContainsIgnoreCase(this, value, true, false); - } - private final boolean isAccidentalSelect(T[] values) { return (values != null && values.length == 1 && values[0] instanceof Select); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Contains.java b/jOOQ/src/main/java/org/jooq/impl/Contains.java index bba44cfa7d..fb569055e9 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Contains.java +++ b/jOOQ/src/main/java/org/jooq/impl/Contains.java @@ -37,60 +37,56 @@ */ 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 static org.jooq.impl.DSL.val; +import static org.jooq.impl.DSL.*; +import static org.jooq.impl.Internal.*; +import static org.jooq.impl.Keywords.*; +import static org.jooq.impl.Names.*; +import static org.jooq.impl.SQLDataType.*; +import static org.jooq.impl.Tools.*; +import static org.jooq.impl.Tools.BooleanDataKey.*; +import static org.jooq.impl.Tools.DataExtendedKey.*; +import static org.jooq.impl.Tools.DataKey.*; +import static org.jooq.SQLDialect.*; + +import org.jooq.*; +import org.jooq.Record; +import org.jooq.conf.*; +import org.jooq.impl.*; +import org.jooq.tools.*; + +import java.util.*; +import java.util.function.*; +import java.util.stream.*; -import org.jooq.Clause; -import org.jooq.Condition; -import org.jooq.Configuration; -import org.jooq.Context; -import org.jooq.Field; /** - * Abstraction for various "contains" operations - * - * @author Lukas Eder + * The CONTAINS statement. */ -final class Contains extends AbstractCondition { - private static final Clause[] CLAUSES = { CONDITION, CONDITION_COMPARISON }; +@SuppressWarnings({ "rawtypes", "unchecked", "unused" }) +final class Contains +extends + AbstractCondition +{ - private final Field lhs; - private final Field rhs; - private final T value; - private final boolean leftWildcard; - private final boolean rightWildcard; + final Field value; + final Field content; - Contains(Field field, T value, boolean leftWildcard, boolean rightWildcard) { - this.lhs = field; - this.rhs = null; - this.value = value; - this.leftWildcard = leftWildcard; - this.rightWildcard = rightWildcard; + Contains( + Field value, + Field content + ) { + + this.value = nullableIf(false, Tools.nullSafe(value, content.getDataType())); + this.content = nullableIf(false, Tools.nullSafe(content, value.getDataType())); } - Contains(Field field, Field rhs, boolean leftWildcard, boolean rightWildcard) { - this.lhs = field; - this.rhs = rhs; - this.value = null; - this.leftWildcard = leftWildcard; - this.rightWildcard = rightWildcard; - } + // ------------------------------------------------------------------------- + // XXX: QueryPart API + // ------------------------------------------------------------------------- @Override public final void accept(Context ctx) { - // [#1107] Some dialects support "contains" operations for ARRAYs - // [#5929] Check both sides of the operation for array types - if (lhs.getDataType().isArray() - || (rhs != null && rhs.getDataType().isArray()) - || (rhs == null && value != null && value.getClass().isArray())) - ctx.visit(new PostgresArrayContains()); - - // "contains" operations on Strings - else { - switch (ctx.family()) { + switch (ctx.family()) { @@ -99,53 +95,49 @@ final class Contains extends AbstractCondition { - - - - - - - - default: - Field[] array = new Field[1 + (leftWildcard ? 1 : 0) + (rightWildcard ? 1 : 0)]; - - int i = 0; - if (leftWildcard) - array[i++] = inline("%"); - - array[i++] = Tools.escapeForLike(rhs == null ? Tools.field(value, lhs) : rhs, ctx.configuration()); - - if (rightWildcard) - array[i++] = inline("%"); - - ctx.visit(lhs.like(DSL.concat(array), Tools.ESCAPE)); - break; + case POSTGRES: + case YUGABYTE: { + // [#1107] Some dialects support "contains" operations for ARRAYs + // [#5929] Check both sides of the operation for array types + if (value.getDataType().isArray() || content.getDataType().isArray()) + ctx.visit(value).sql(" @> ").visit(content); + else + acceptDefault(ctx); + break; } + + default: + acceptDefault(ctx); + break; } } - /** - * The Postgres array contains operator - */ - private class PostgresArrayContains extends AbstractCondition { - @Override - public final void accept(Context ctx) { - ctx.visit(lhs).sql(" @> ").visit(rhs()); - } - @Override - public final Clause[] clauses(Context ctx) { - return CLAUSES; - } - private final Field rhs() { - return (rhs == null) ? val(value, lhs) : rhs; - } + + + + + + + private final void acceptDefault(Context ctx) { + ctx.visit(value.like(DSL.concat(inline("%"), Tools.escapeForLike(content, ctx.configuration()), inline("%")), Tools.ESCAPE)); } + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + @Override - public final Clause[] clauses(Context ctx) { - return CLAUSES; + public boolean equals(Object that) { + if (that instanceof Contains) { + return + StringUtils.equals(value, ((Contains) that).value) && + StringUtils.equals(content, ((Contains) that).content) + ; + } + else + return super.equals(that); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java b/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java index 11225ebe5a..06c32df2ee 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java +++ b/jOOQ/src/main/java/org/jooq/impl/ContainsIgnoreCase.java @@ -37,37 +37,53 @@ */ 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 static org.jooq.impl.DSL.*; +import static org.jooq.impl.Internal.*; +import static org.jooq.impl.Keywords.*; +import static org.jooq.impl.Names.*; +import static org.jooq.impl.SQLDataType.*; +import static org.jooq.impl.Tools.*; +import static org.jooq.impl.Tools.BooleanDataKey.*; +import static org.jooq.impl.Tools.DataExtendedKey.*; +import static org.jooq.impl.Tools.DataKey.*; +import static org.jooq.SQLDialect.*; + +import org.jooq.*; +import org.jooq.Record; +import org.jooq.conf.*; +import org.jooq.impl.*; +import org.jooq.tools.*; + +import java.util.*; +import java.util.function.*; +import java.util.stream.*; -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 + * The CONTAINS IGNORE CASE statement. */ -final class ContainsIgnoreCase extends AbstractCondition { +@SuppressWarnings({ "rawtypes", "unchecked", "unused" }) +final class ContainsIgnoreCase +extends + AbstractCondition +{ - private static final Clause[] CLAUSES = { CONDITION, CONDITION_COMPARISON }; + final Field value; + final Field content; - private final Field lhs; - private final Field rhs; - private final boolean leftWildcard; - private final boolean rightWildcard; + ContainsIgnoreCase( + Field value, + Field content + ) { - ContainsIgnoreCase(Field field, Field rhs, boolean leftWildcard, boolean rightWildcard) { - this.lhs = field; - this.rhs = rhs; - this.leftWildcard = leftWildcard; - this.rightWildcard = rightWildcard; + this.value = nullableIf(false, Tools.nullSafe(value, content.getDataType())); + this.content = nullableIf(false, Tools.nullSafe(content, value.getDataType())); } + // ------------------------------------------------------------------------- + // XXX: QueryPart API + // ------------------------------------------------------------------------- + @Override public final void accept(Context ctx) { switch (ctx.family()) { @@ -77,31 +93,34 @@ final class ContainsIgnoreCase extends AbstractCondition { - - - - - - default: - Field[] array = new Field[1 + (leftWildcard ? 1 : 0) + (rightWildcard ? 1 : 0)]; - - int i = 0; - if (leftWildcard) - array[i++] = inline("%"); - - array[i++] = Tools.escapeForLike(rhs, ctx.configuration()); - - if (rightWildcard) - array[i++] = inline("%"); - - ctx.visit(lhs.likeIgnoreCase(DSL.concat(array), Tools.ESCAPE)); + ctx.visit(value.likeIgnoreCase(DSL.concat(inline("%"), Tools.escapeForLike(content, ctx.configuration()), inline("%")), Tools.ESCAPE)); break; } } + + + + + + + + + + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + @Override - public final Clause[] clauses(Context ctx) { - return CLAUSES; + public boolean equals(Object that) { + if (that instanceof ContainsIgnoreCase) { + return + StringUtils.equals(value, ((ContainsIgnoreCase) that).value) && + StringUtils.equals(content, ((ContainsIgnoreCase) that).content) + ; + } + else + return super.equals(that); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/EndsWith.java b/jOOQ/src/main/java/org/jooq/impl/EndsWith.java new file mode 100644 index 0000000000..a971b02ecc --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/EndsWith.java @@ -0,0 +1,126 @@ +/* + * 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.impl.DSL.*; +import static org.jooq.impl.Internal.*; +import static org.jooq.impl.Keywords.*; +import static org.jooq.impl.Names.*; +import static org.jooq.impl.SQLDataType.*; +import static org.jooq.impl.Tools.*; +import static org.jooq.impl.Tools.BooleanDataKey.*; +import static org.jooq.impl.Tools.DataExtendedKey.*; +import static org.jooq.impl.Tools.DataKey.*; +import static org.jooq.SQLDialect.*; + +import org.jooq.*; +import org.jooq.Record; +import org.jooq.conf.*; +import org.jooq.impl.*; +import org.jooq.tools.*; + +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + + +/** + * The ENDS WITH statement. + */ +@SuppressWarnings({ "rawtypes", "unchecked", "unused" }) +final class EndsWith +extends + AbstractCondition +{ + + final Field string; + final Field suffix; + + EndsWith( + Field string, + Field suffix + ) { + + this.string = nullableIf(false, Tools.nullSafe(string, suffix.getDataType())); + this.suffix = nullableIf(false, Tools.nullSafe(suffix, string.getDataType())); + } + + // ------------------------------------------------------------------------- + // XXX: QueryPart API + // ------------------------------------------------------------------------- + + @Override + public final void accept(Context ctx) { + switch (ctx.family()) { + + + + + + + default: + ctx.visit(string.like(DSL.concat(inline("%"), Tools.escapeForLike(suffix, ctx.configuration())), Tools.ESCAPE)); + break; + } + } + + + + + + + + + + + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + + @Override + public boolean equals(Object that) { + if (that instanceof EndsWith) { + return + StringUtils.equals(string, ((EndsWith) that).string) && + StringUtils.equals(suffix, ((EndsWith) that).suffix) + ; + } + else + return super.equals(that); + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/EndsWithIgnoreCase.java b/jOOQ/src/main/java/org/jooq/impl/EndsWithIgnoreCase.java new file mode 100644 index 0000000000..191643f50a --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/EndsWithIgnoreCase.java @@ -0,0 +1,126 @@ +/* + * 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.impl.DSL.*; +import static org.jooq.impl.Internal.*; +import static org.jooq.impl.Keywords.*; +import static org.jooq.impl.Names.*; +import static org.jooq.impl.SQLDataType.*; +import static org.jooq.impl.Tools.*; +import static org.jooq.impl.Tools.BooleanDataKey.*; +import static org.jooq.impl.Tools.DataExtendedKey.*; +import static org.jooq.impl.Tools.DataKey.*; +import static org.jooq.SQLDialect.*; + +import org.jooq.*; +import org.jooq.Record; +import org.jooq.conf.*; +import org.jooq.impl.*; +import org.jooq.tools.*; + +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + + +/** + * The ENDS WITH IGNORE CASE statement. + */ +@SuppressWarnings({ "rawtypes", "unchecked", "unused" }) +final class EndsWithIgnoreCase +extends + AbstractCondition +{ + + final Field string; + final Field suffix; + + EndsWithIgnoreCase( + Field string, + Field suffix + ) { + + this.string = nullableIf(false, Tools.nullSafe(string, suffix.getDataType())); + this.suffix = nullableIf(false, Tools.nullSafe(suffix, string.getDataType())); + } + + // ------------------------------------------------------------------------- + // XXX: QueryPart API + // ------------------------------------------------------------------------- + + @Override + public final void accept(Context ctx) { + switch (ctx.family()) { + + + + + + + default: + ctx.visit(string.likeIgnoreCase(DSL.concat(inline("%"), Tools.escapeForLike(suffix, ctx.configuration())), Tools.ESCAPE)); + break; + } + } + + + + + + + + + + + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + + @Override + public boolean equals(Object that) { + if (that instanceof EndsWithIgnoreCase) { + return + StringUtils.equals(string, ((EndsWithIgnoreCase) that).string) && + StringUtils.equals(suffix, ((EndsWithIgnoreCase) that).suffix) + ; + } + else + return super.equals(that); + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/StartsWith.java b/jOOQ/src/main/java/org/jooq/impl/StartsWith.java new file mode 100644 index 0000000000..046075bf6a --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/StartsWith.java @@ -0,0 +1,126 @@ +/* + * 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.impl.DSL.*; +import static org.jooq.impl.Internal.*; +import static org.jooq.impl.Keywords.*; +import static org.jooq.impl.Names.*; +import static org.jooq.impl.SQLDataType.*; +import static org.jooq.impl.Tools.*; +import static org.jooq.impl.Tools.BooleanDataKey.*; +import static org.jooq.impl.Tools.DataExtendedKey.*; +import static org.jooq.impl.Tools.DataKey.*; +import static org.jooq.SQLDialect.*; + +import org.jooq.*; +import org.jooq.Record; +import org.jooq.conf.*; +import org.jooq.impl.*; +import org.jooq.tools.*; + +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + + +/** + * The STARTS WITH statement. + */ +@SuppressWarnings({ "rawtypes", "unchecked", "unused" }) +final class StartsWith +extends + AbstractCondition +{ + + final Field string; + final Field prefix; + + StartsWith( + Field string, + Field prefix + ) { + + this.string = nullableIf(false, Tools.nullSafe(string, prefix.getDataType())); + this.prefix = nullableIf(false, Tools.nullSafe(prefix, string.getDataType())); + } + + // ------------------------------------------------------------------------- + // XXX: QueryPart API + // ------------------------------------------------------------------------- + + @Override + public final void accept(Context ctx) { + switch (ctx.family()) { + + + + + + + default: + ctx.visit(string.like(DSL.concat(Tools.escapeForLike(prefix, ctx.configuration()), inline("%")), Tools.ESCAPE)); + break; + } + } + + + + + + + + + + + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + + @Override + public boolean equals(Object that) { + if (that instanceof StartsWith) { + return + StringUtils.equals(string, ((StartsWith) that).string) && + StringUtils.equals(prefix, ((StartsWith) that).prefix) + ; + } + else + return super.equals(that); + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/StartsWithIgnoreCase.java b/jOOQ/src/main/java/org/jooq/impl/StartsWithIgnoreCase.java new file mode 100644 index 0000000000..0543499d0b --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/StartsWithIgnoreCase.java @@ -0,0 +1,126 @@ +/* + * 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.impl.DSL.*; +import static org.jooq.impl.Internal.*; +import static org.jooq.impl.Keywords.*; +import static org.jooq.impl.Names.*; +import static org.jooq.impl.SQLDataType.*; +import static org.jooq.impl.Tools.*; +import static org.jooq.impl.Tools.BooleanDataKey.*; +import static org.jooq.impl.Tools.DataExtendedKey.*; +import static org.jooq.impl.Tools.DataKey.*; +import static org.jooq.SQLDialect.*; + +import org.jooq.*; +import org.jooq.Record; +import org.jooq.conf.*; +import org.jooq.impl.*; +import org.jooq.tools.*; + +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + + +/** + * The STARTS WITH IGNORE CASE statement. + */ +@SuppressWarnings({ "rawtypes", "unchecked", "unused" }) +final class StartsWithIgnoreCase +extends + AbstractCondition +{ + + final Field string; + final Field prefix; + + StartsWithIgnoreCase( + Field string, + Field prefix + ) { + + this.string = nullableIf(false, Tools.nullSafe(string, prefix.getDataType())); + this.prefix = nullableIf(false, Tools.nullSafe(prefix, string.getDataType())); + } + + // ------------------------------------------------------------------------- + // XXX: QueryPart API + // ------------------------------------------------------------------------- + + @Override + public final void accept(Context ctx) { + switch (ctx.family()) { + + + + + + + default: + ctx.visit(string.likeIgnoreCase(DSL.concat(Tools.escapeForLike(prefix, ctx.configuration()), inline("%")), Tools.ESCAPE)); + break; + } + } + + + + + + + + + + + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + + @Override + public boolean equals(Object that) { + if (that instanceof StartsWithIgnoreCase) { + return + StringUtils.equals(string, ((StartsWithIgnoreCase) that).string) && + StringUtils.equals(prefix, ((StartsWithIgnoreCase) that).prefix) + ; + } + else + return super.equals(that); + } +}