diff --git a/jOOQ/src/main/java/org/jooq/Field.java b/jOOQ/src/main/java/org/jooq/Field.java
index 08844b9f69..923ac74969 100644
--- a/jOOQ/src/main/java/org/jooq/Field.java
+++ b/jOOQ/src/main/java/org/jooq/Field.java
@@ -1495,6 +1495,25 @@ extends
@Support
Condition like(String value, char escape);
+ /**
+ * Create a condition to pattern-check this field against a quantified select.
+ *
+ * For example a query like {@code field.like(any("a%", "b%"))} translates into
+ * the SQL {@code (field like 'a%' or field like 'b%')}.
+ *
+ * @see DSL#all(Field)
+ * @see DSL#all(Field...)
+ * @see DSL#all(Select)
+ * @see DSL#all(Object...)
+ * @see DSL#any(Field)
+ * @see DSL#any(Field...)
+ * @see DSL#any(Select)
+ * @see DSL#any(Object...)
+ * @see LikeEscapeStep#escape(char)
+ */
+ @Support
+ LikeEscapeStep like(QuantifiedSelect> query);
+
/**
* Create a condition to case-insensitively pattern-check this field against
* a field.
@@ -1579,6 +1598,25 @@ extends
@Support
Condition notLike(String value, char escape);
+ /**
+ * Create a condition to pattern-check this field against a quantified select.
+ *
+ * For example a query like {@code field.notLike(any("a%", "b%"))} translates into
+ * the SQL {@code (field not like 'a%' or field not like 'b%')}.
+ *
+ * @see DSL#all(Field)
+ * @see DSL#all(Field...)
+ * @see DSL#all(Select)
+ * @see DSL#all(Object...)
+ * @see DSL#any(Field)
+ * @see DSL#any(Field...)
+ * @see DSL#any(Select)
+ * @see DSL#any(Object...)
+ * @see LikeEscapeStep#escape(char)
+ */
+ @Support
+ LikeEscapeStep notLike(QuantifiedSelect> query);
+
/**
* Create a condition to case-insensitively pattern-check this field against
* a field.
@@ -1627,130 +1665,6 @@ extends
@Support
Condition notLikeIgnoreCase(String value, char escape);
- /**
- * Create a condition to pattern-check this field against any element in an array of values.
- *
- * SQL: (this like value0 or this like value1 or ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- LikeEscapeStep likeAny(String... values);
-
- /**
- * Create a condition to pattern-check this field against any element in an array of fields.
- *
- * SQL: (this like field0 or this like field1 or ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- @SuppressWarnings("unchecked")
- LikeEscapeStep likeAny(Field... fields);
-
- /**
- * Create a condition to pattern-check this field against any element in a collection of fields or values.
- *
- * SQL: (this like field0 or this like field1 or ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- LikeEscapeStep likeAny(Collection> values);
-
- /**
- * Create a condition to negatively pattern-check this field against any element in an array of values.
- *
- * SQL: (this not like value0 or this not like value1 or ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- LikeEscapeStep notLikeAny(String... values);
-
- /**
- * Create a condition to negatively pattern-check this field against any element in an array of values.
- *
- * SQL: (this not like value0 or this not like value1 or ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- @SuppressWarnings("unchecked")
- LikeEscapeStep notLikeAny(Field... fields);
-
- /**
- * Create a condition to negatively pattern-check this field against any element in an array of values.
- *
- * SQL: (this not like value0 or this not like value1 or ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- LikeEscapeStep notLikeAny(Collection> values);
-
- /**
- * Create a condition to pattern-check this field against all elements in an array of values.
- *
- * SQL: (this like value0 and this like value1 and ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- LikeEscapeStep likeAll(String... values);
-
- /**
- * Create a condition to pattern-check this field against all elements in an array of fields.
- *
- * SQL: (this like field0 and this like field1 and ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- @SuppressWarnings("unchecked")
- LikeEscapeStep likeAll(Field... fields);
-
- /**
- * Create a condition to pattern-check this field against all elements in a collection of fields or values.
- *
- * SQL: (this like field0 and this like field1 and ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- LikeEscapeStep likeAll(Collection> values);
-
- /**
- * Create a condition to negatively pattern-check this field against all elements in an array of values.
- *
- * SQL: (this not like value0 and this not like value1 and ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- LikeEscapeStep notLikeAll(String... values);
-
- /**
- * Create a condition to negatively pattern-check this field against all elements in an array of fields.
- *
- * SQL: (this not like field0 and this not like field1 and ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- @SuppressWarnings("unchecked")
- LikeEscapeStep notLikeAll(Field... fields);
-
- /**
- * Create a condition to negatively pattern-check this field against all elements in a collection of fields or values.
- *
- * SQL: (this not like field0 and this not like field1 and ...)
- *
- * @see LikeEscapeStep#escape(char)
- */
- @Support
- LikeEscapeStep notLikeAll(Collection> values);
-
/**
* 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 1ea86249d5..67f23503a8 100644
--- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java
+++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java
@@ -782,6 +782,11 @@ abstract class AbstractField extends AbstractNamed implements Field {
return like(field).escape(escape);
}
+ @Override
+ public LikeEscapeStep like(QuantifiedSelect> query) {
+ return new QuantifiedComparisonCondition(query, this, LIKE);
+ }
+
@Override
public final LikeEscapeStep likeIgnoreCase(String value) {
return likeIgnoreCase(Tools.field(value));
@@ -832,6 +837,11 @@ abstract class AbstractField extends AbstractNamed implements Field {
return notLike(field).escape(escape);
}
+ @Override
+ public LikeEscapeStep notLike(QuantifiedSelect> query) {
+ return new QuantifiedComparisonCondition(query, this, NOT_LIKE);
+ }
+
@Override
public final LikeEscapeStep notLikeIgnoreCase(String value) {
return notLikeIgnoreCase(Tools.field(value));
@@ -852,70 +862,6 @@ abstract class AbstractField extends AbstractNamed implements Field {
return notLikeIgnoreCase(field).escape(escape);
}
- @Override
- public final LikeEscapeStep likeAny(String... values) {
- return likeAny(Tools.fields(values));
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public final LikeEscapeStep likeAny(Field... fields) {
- return likeAny(Arrays.asList(fields));
- }
-
- @Override
- public final LikeEscapeStep likeAny(Collection> values) {
- return new CombinedCompareCondition(this, LIKE, Quantifier.ANY, Tools.fields(values, SQLDataType.VARCHAR));
- }
-
- @Override
- public final LikeEscapeStep notLikeAny(String... values) {
- return notLikeAny(Tools.fields(values));
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public final LikeEscapeStep notLikeAny(Field... fields) {
- return notLikeAny(Arrays.asList(fields));
- }
-
- @Override
- public final LikeEscapeStep notLikeAny(Collection> values) {
- return new CombinedCompareCondition(this, NOT_LIKE, Quantifier.ANY, Tools.fields(values, SQLDataType.VARCHAR));
- }
-
- @Override
- public final LikeEscapeStep likeAll(String... values) {
- return likeAll(Tools.fields(values));
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public final LikeEscapeStep likeAll(Field... fields) {
- return likeAll(Arrays.asList(fields));
- }
-
- @Override
- public final LikeEscapeStep likeAll(Collection> values) {
- return new CombinedCompareCondition(this, LIKE, Quantifier.ALL, Tools.fields(values, SQLDataType.VARCHAR));
- }
-
- @Override
- public final LikeEscapeStep notLikeAll(String... values) {
- return notLikeAll(Tools.fields(values));
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public final LikeEscapeStep notLikeAll(Field... fields) {
- return notLikeAll(Arrays.asList(fields));
- }
-
- @Override
- public final LikeEscapeStep notLikeAll(Collection> values) {
- return new CombinedCompareCondition(this, NOT_LIKE, Quantifier.ALL, Tools.fields(values, SQLDataType.VARCHAR));
- }
-
@Override
public final Condition notLikeRegex(String pattern) {
return likeRegex(pattern).not();
diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java
index 33170a18ae..89f1cc88db 100644
--- a/jOOQ/src/main/java/org/jooq/impl/DSL.java
+++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java
@@ -8137,6 +8137,7 @@ public class DSL {
* @see Field#greaterOrEqual(QuantifiedSelect)
* @see Field#lessThan(QuantifiedSelect)
* @see Field#lessOrEqual(QuantifiedSelect)
+ * @see Field#like(QuantifiedSelect)
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
public static QuantifiedSelect all(Select select) {
@@ -8156,6 +8157,7 @@ public class DSL {
* @see Field#greaterOrEqual(QuantifiedSelect)
* @see Field#lessThan(QuantifiedSelect)
* @see Field#lessOrEqual(QuantifiedSelect)
+ * @see Field#like(QuantifiedSelect)
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
public static QuantifiedSelect> all(T... array) {
@@ -8175,12 +8177,36 @@ public class DSL {
* @see Field#greaterOrEqual(QuantifiedSelect)
* @see Field#lessThan(QuantifiedSelect)
* @see Field#lessOrEqual(QuantifiedSelect)
+ * @see Field#like(QuantifiedSelect)
*/
@Support({ H2, HSQLDB, POSTGRES })
public static QuantifiedSelect> all(Field array) {
return new QuantifiedSelectImpl>(Quantifier.ALL, array);
}
+ /**
+ * Create an ALL quantified select to be used in quantified
+ * comparison predicate expressions.
+ *
+ * This is natively supported by {@link SQLDialect#POSTGRES}. Other dialects
+ * will render a subselect unnesting the array.
+ *
+ * @see Field#equal(QuantifiedSelect)
+ * @see Field#notEqual(QuantifiedSelect)
+ * @see Field#greaterThan(QuantifiedSelect)
+ * @see Field#greaterOrEqual(QuantifiedSelect)
+ * @see Field#lessThan(QuantifiedSelect)
+ * @see Field#lessOrEqual(QuantifiedSelect)
+ * @see Field#like(QuantifiedSelect)
+ */
+ @Support
+
+ @SafeVarargs
+
+ public static QuantifiedSelect> all(Field... fields) {
+ return new QuantifiedSelectImpl>(Quantifier.ALL, fields);
+ }
+
/**
* Create an ANY quantified select to be used in quantified
* comparison predicate expressions.
@@ -8191,6 +8217,7 @@ public class DSL {
* @see Field#greaterOrEqual(QuantifiedSelect)
* @see Field#lessThan(QuantifiedSelect)
* @see Field#lessOrEqual(QuantifiedSelect)
+ * @see Field#like(QuantifiedSelect)
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
public static QuantifiedSelect any(Select select) {
@@ -8210,6 +8237,7 @@ public class DSL {
* @see Field#greaterOrEqual(QuantifiedSelect)
* @see Field#lessThan(QuantifiedSelect)
* @see Field#lessOrEqual(QuantifiedSelect)
+ * @see Field#like(QuantifiedSelect)
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
public static QuantifiedSelect> any(T... array) {
@@ -8229,12 +8257,36 @@ public class DSL {
* @see Field#greaterOrEqual(QuantifiedSelect)
* @see Field#lessThan(QuantifiedSelect)
* @see Field#lessOrEqual(QuantifiedSelect)
+ * @see Field#like(QuantifiedSelect)
*/
@Support({ H2, HSQLDB, POSTGRES })
public static QuantifiedSelect> any(Field array) {
return new QuantifiedSelectImpl>(Quantifier.ANY, array);
}
+ /**
+ * Create an ANY quantified select to be used in quantified
+ * comparison predicate expressions.
+ *
+ * This is natively supported by {@link SQLDialect#POSTGRES}. Other dialects
+ * will render a subselect unnesting the array.
+ *
+ * @see Field#equal(QuantifiedSelect)
+ * @see Field#notEqual(QuantifiedSelect)
+ * @see Field#greaterThan(QuantifiedSelect)
+ * @see Field#greaterOrEqual(QuantifiedSelect)
+ * @see Field#lessThan(QuantifiedSelect)
+ * @see Field#lessOrEqual(QuantifiedSelect)
+ * @see Field#like(QuantifiedSelect)
+ */
+ @Support
+
+ @SafeVarargs
+
+ public static QuantifiedSelect> any(Field... fields) {
+ return new QuantifiedSelectImpl>(Quantifier.ANY, fields);
+ }
+
// -------------------------------------------------------------------------
// XXX Access control
// -------------------------------------------------------------------------
diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java
index 5d086c3dbf..fd972e6951 100644
--- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java
@@ -51,6 +51,8 @@ import static org.jooq.conf.ParseWithMetaLookups.IGNORE_ON_FAILURE;
import static org.jooq.conf.ParseWithMetaLookups.THROW_ON_FAILURE;
import static org.jooq.impl.DSL.abs;
import static org.jooq.impl.DSL.acos;
+import static org.jooq.impl.DSL.all;
+import static org.jooq.impl.DSL.any;
import static org.jooq.impl.DSL.arrayAgg;
import static org.jooq.impl.DSL.arrayAggDistinct;
import static org.jooq.impl.DSL.ascii;
@@ -4400,39 +4402,61 @@ final class ParserImpl implements Parser {
else if (left instanceof Field && parseKeywordIf(ctx, "LIKE")) {
if (parseKeywordIf(ctx, "ANY")) {
parse(ctx, '(');
- List> fields = null;
- if (parseIf(ctx, ')'))
- fields = Collections.> emptyList();
- else {
- fields = new ArrayList>();
- do {
- fields.add(toField(ctx, parseConcat(ctx, null)));
- }
- while (parseIf(ctx, ','));
+ if (peekKeyword(ctx, "SELECT") || peekKeyword(ctx, "SEL")) {
+ SelectQueryImpl select = parseSelect(ctx);
parse(ctx, ')');
+ boolean escape = parseKeywordIf(ctx, "ESCAPE");
+ char character = escape ? parseCharacterLiteral(ctx) : ' ';
+ LikeEscapeStep result = not ? ((Field) left).notLike(any(select)) : ((Field) left).like(any(select));
+ return escape ? result.escape(character) : result;
+ }
+ else {
+ List> fields = null;
+ if (parseIf(ctx, ')'))
+ fields = Collections.> emptyList();
+ else {
+ fields = new ArrayList>();
+ do {
+ fields.add(toField(ctx, parseConcat(ctx, null)));
+ }
+ while (parseIf(ctx, ','));
+ parse(ctx, ')');
+ }
+ boolean escape = parseKeywordIf(ctx, "ESCAPE");
+ char character = escape ? parseCharacterLiteral(ctx) : ' ';
+ Field>[] fieldArray = fields.toArray(new Field[0]);
+ LikeEscapeStep result = not ? ((Field) left).notLike(any(fieldArray)) : ((Field) left).like(any(fieldArray));
+ return escape ? result.escape(character) : result;
}
- boolean escape = parseKeywordIf(ctx, "ESCAPE");
- char character = escape ? parseCharacterLiteral(ctx) : ' ';
- LikeEscapeStep result = not ? ((Field) left).notLikeAny(fields) : ((Field) left).likeAny(fields);
- return escape ? result.escape(character) : result;
}
else if (parseKeywordIf(ctx, "ALL")) {
parse(ctx, '(');
- List> fields = null;
- if (parseIf(ctx, ')'))
- fields = Collections.> emptyList();
- else {
- fields = new ArrayList>();
- do {
- fields.add(toField(ctx, parseConcat(ctx, null)));
- }
- while (parseIf(ctx, ','));
+ if (peekKeyword(ctx, "SELECT") || peekKeyword(ctx, "SEL")) {
+ SelectQueryImpl select = parseSelect(ctx);
parse(ctx, ')');
+ boolean escape = parseKeywordIf(ctx, "ESCAPE");
+ char character = escape ? parseCharacterLiteral(ctx) : ' ';
+ LikeEscapeStep result = not ? ((Field) left).notLike(all(select)) : ((Field) left).like(all(select));
+ return escape ? result.escape(character) : result;
+ }
+ else {
+ List> fields = null;
+ if (parseIf(ctx, ')'))
+ fields = Collections.> emptyList();
+ else {
+ fields = new ArrayList>();
+ do {
+ fields.add(toField(ctx, parseConcat(ctx, null)));
+ }
+ while (parseIf(ctx, ','));
+ parse(ctx, ')');
+ }
+ boolean escape = parseKeywordIf(ctx, "ESCAPE");
+ char character = escape ? parseCharacterLiteral(ctx) : ' ';
+ Field>[] fieldArray = fields.toArray(new Field[0]);
+ LikeEscapeStep result = not ? ((Field) left).notLike(all(fieldArray)) : ((Field) left).like(all(fieldArray));
+ return escape ? result.escape(character) : result;
}
- boolean escape = parseKeywordIf(ctx, "ESCAPE");
- char character = escape ? parseCharacterLiteral(ctx) : ' ';
- LikeEscapeStep result = not ? ((Field) left).notLikeAll(fields) : ((Field) left).likeAll(fields);
- return escape ? result.escape(character) : result;
}
else {
Field right = toField(ctx, parseConcat(ctx, null));
diff --git a/jOOQ/src/main/java/org/jooq/impl/QuantifiedComparisonCondition.java b/jOOQ/src/main/java/org/jooq/impl/QuantifiedComparisonCondition.java
index 33f7b01aa4..70d22b6a8a 100644
--- a/jOOQ/src/main/java/org/jooq/impl/QuantifiedComparisonCondition.java
+++ b/jOOQ/src/main/java/org/jooq/impl/QuantifiedComparisonCondition.java
@@ -41,27 +41,45 @@ package org.jooq.impl;
import static org.jooq.Clause.CONDITION;
import static org.jooq.Clause.CONDITION_BETWEEN;
+import static org.jooq.impl.DSL.inline;
+import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.row;
+import static org.jooq.impl.DSL.select;
+import static org.jooq.impl.SQLDataType.VARCHAR;
import static org.jooq.impl.Tools.embeddedFields;
import static org.jooq.impl.Tools.isEmbeddable;
+import static org.jooq.tools.Convert.convert;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
import org.jooq.Clause;
import org.jooq.Comparator;
+import org.jooq.Condition;
import org.jooq.Context;
import org.jooq.Field;
+import org.jooq.LikeEscapeStep;
+import org.jooq.Operator;
+import org.jooq.Param;
import org.jooq.QuantifiedSelect;
+import org.jooq.Record1;
+import org.jooq.Select;
+import org.jooq.Table;
/**
* @author Lukas Eder
*/
-final class QuantifiedComparisonCondition extends AbstractCondition {
+final class QuantifiedComparisonCondition extends AbstractCondition implements LikeEscapeStep {
- private static final long serialVersionUID = -402776705884329740L;
- private static final Clause[] CLAUSES = { CONDITION, CONDITION_BETWEEN };
+ private static final long serialVersionUID = -402776705884329740L;
+ private static final Clause[] CLAUSES = { CONDITION, CONDITION_BETWEEN };
+ private static final EnumSet SYNTHETIC_OPERATORS = EnumSet.of(Comparator.LIKE, Comparator.NOT_LIKE, Comparator.LIKE_IGNORE_CASE, Comparator.NOT_LIKE_IGNORE_CASE, Comparator.SIMILAR_TO, Comparator.NOT_SIMILAR_TO);
- private final QuantifiedSelect> query;
- private final Field> field;
- private final Comparator comparator;
+ private final QuantifiedSelect> query;
+ private final Field> field;
+ private final Comparator comparator;
+ private Character escape;
QuantifiedComparisonCondition(QuantifiedSelect> query, Field> field, Comparator comparator) {
this.query = query;
@@ -69,6 +87,12 @@ final class QuantifiedComparisonCondition extends AbstractCondition {
this.comparator = comparator;
}
+ @Override
+ public Condition escape(char c) {
+ this.escape = c;
+ return this;
+ }
+
@Override
public final void accept(Context> ctx) {
if (isEmbeddable(field))
@@ -77,12 +101,135 @@ final class QuantifiedComparisonCondition extends AbstractCondition {
accept0(ctx);
}
+ @SuppressWarnings({ "unchecked", "null" })
private final void accept0(Context> ctx) {
+ Field extends Object[]> array = ((QuantifiedSelectImpl>) query).array;
+ Field[] values = (Field[]) ((QuantifiedSelectImpl>) query).values;
+ Quantifier quantifier = ((QuantifiedSelectImpl>) query).quantifier;
+ Select> subquery = ((QuantifiedSelectImpl>) query).query;
+
+ if (values != null || array instanceof Param>) {
+ List conditions = new ArrayList();
+ if (values != null)
+ for (Field value : values)
+ conditions.add(comparisonCondition(comparator, value));
+ else
+ for (Object value : ((Param extends Object[]>) array).getValue())
+ conditions.add(value instanceof Field ? comparisonCondition(comparator, (Field) value) : comparisonCondition(comparator, value));
+
+ Condition combinedCondition = CombinedCondition.of(quantifier == Quantifier.ALL ? Operator.AND : Operator.OR, conditions);
+ ctx.visit(combinedCondition);
+ }
+ else if ((array != null || subquery != null) && SYNTHETIC_OPERATORS.contains(comparator)) {
+ Field pattern = DSL.field(name("pattern"), VARCHAR);
+ Condition cond;
+ Field lhs;
+ switch (comparator) {
+ case NOT_LIKE:
+ case NOT_SIMILAR_TO:
+ case NOT_LIKE_IGNORE_CASE:
+ cond = comparisonCondition(inverse(comparator), pattern);
+ lhs = inline(false);
+ break;
+ case LIKE:
+ case SIMILAR_TO:
+ case LIKE_IGNORE_CASE:
+ cond = comparisonCondition(comparator, pattern);
+ lhs = inline(true);
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+
+ Table> t = (array != null ? new ArrayTable(array) : subquery).asTable("t", "pattern");
+ Select> select = select(DSL.field(cond)).from(t);
+ ctx.visit(lhs.eq(quantifier.apply(select)));
+ }
+ else {
+ accept1(ctx);
+ }
+ }
+
+ private final void accept1(Context> ctx) {
ctx.visit(field)
- .sql(' ')
- .visit(comparator.toKeyword())
- .sql(' ')
- .visit(query);
+ .sql(' ')
+ .visit(comparator.toKeyword())
+ .sql(' ')
+ .visit(query);
+ }
+
+ private Comparator inverse(Comparator operator) {
+ switch (operator) {
+ case IN: return Comparator.NOT_IN;
+ case NOT_IN: return Comparator.IN;
+ case EQUALS: return Comparator.NOT_EQUALS;
+ case NOT_EQUALS: return Comparator.EQUALS;
+ case LESS: return Comparator.GREATER_OR_EQUAL;
+ case LESS_OR_EQUAL: return Comparator.GREATER;
+ case GREATER: return Comparator.LESS_OR_EQUAL;
+ case GREATER_OR_EQUAL: return Comparator.LESS;
+ case IS_DISTINCT_FROM: return Comparator.IS_NOT_DISTINCT_FROM;
+ case IS_NOT_DISTINCT_FROM: return Comparator.IS_DISTINCT_FROM;
+ case LIKE: return Comparator.NOT_LIKE;
+ case NOT_LIKE: return Comparator.LIKE;
+ case SIMILAR_TO: return Comparator.NOT_SIMILAR_TO;
+ case NOT_SIMILAR_TO: return Comparator.SIMILAR_TO;
+ case LIKE_IGNORE_CASE: return Comparator.NOT_LIKE_IGNORE_CASE;
+ case NOT_LIKE_IGNORE_CASE: return Comparator.LIKE_IGNORE_CASE;
+ default: throw new IllegalStateException();
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private Condition comparisonCondition(Comparator operator, Field value) {
+ switch (operator) {
+ case LIKE:
+ return escape != null ? field.like(value, escape) : field.like(value);
+
+ case NOT_LIKE:
+ return escape != null ? field.notLike(value, escape) : field.notLike(value);
+
+ case SIMILAR_TO:
+ return escape != null ? field.similarTo(value, escape) : field.similarTo(value);
+
+ case NOT_SIMILAR_TO:
+ return escape != null ? field.notSimilarTo(value, escape) : field.notSimilarTo(value);
+
+ case LIKE_IGNORE_CASE:
+ return escape != null ? field.likeIgnoreCase(value, escape) : field.likeIgnoreCase(value);
+
+ case NOT_LIKE_IGNORE_CASE:
+ return escape != null ? field.notLikeIgnoreCase(value, escape) : field.notLikeIgnoreCase(value);
+
+ default:
+ return ((Field) field).compare(operator, value);
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private Condition comparisonCondition(Comparator operator, Object value) {
+ switch (operator) {
+ case LIKE:
+ return escape != null ? field.like(convert(value, String.class), escape) : field.like(convert(value, String.class));
+
+ case NOT_LIKE:
+ return escape != null ? field.notLike(convert(value, String.class), escape) : field.notLike(convert(value, String.class));
+
+ case SIMILAR_TO:
+ return escape != null ? field.similarTo(convert(value, String.class), escape) : field.similarTo(convert(value, String.class));
+
+ case NOT_SIMILAR_TO:
+ return escape != null ? field.notSimilarTo(convert(value, String.class), escape) : field.notSimilarTo(convert(value, String.class));
+
+ case LIKE_IGNORE_CASE:
+ return escape != null ? field.likeIgnoreCase(convert(value, String.class), escape) : field.likeIgnoreCase(convert(value, String.class));
+
+ case NOT_LIKE_IGNORE_CASE:
+ return escape != null ? field.notLikeIgnoreCase(convert(value, String.class), escape) : field.notLikeIgnoreCase(convert(value, String.class));
+
+ default:
+ return ((Field) field).compare(operator, value);
+ }
}
@Override
diff --git a/jOOQ/src/main/java/org/jooq/impl/QuantifiedSelectImpl.java b/jOOQ/src/main/java/org/jooq/impl/QuantifiedSelectImpl.java
index 9c313d9b67..47982a95f1 100644
--- a/jOOQ/src/main/java/org/jooq/impl/QuantifiedSelectImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/QuantifiedSelectImpl.java
@@ -48,7 +48,7 @@ import org.jooq.Context;
import org.jooq.Field;
import org.jooq.Param;
import org.jooq.QuantifiedSelect;
-import org.jooq.QueryPartInternal;
+import org.jooq.QueryPart;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Select;
@@ -62,22 +62,32 @@ final class QuantifiedSelectImpl extends AbstractQueryPart imp
/**
* Generated UID
*/
- private static final long serialVersionUID = -1224570388944748450L;
+ private static final long serialVersionUID = -1224570388944748450L;
- private final Quantifier quantifier;
- private final Select query;
- private final Field extends Object[]> array;
+ final Quantifier quantifier;
+ final Select query;
+ final Field extends Object[]> array;
+ final Field>[] values;
QuantifiedSelectImpl(Quantifier quantifier, Select query) {
this.quantifier = quantifier;
this.query = query;
this.array = null;
+ this.values = null;
}
QuantifiedSelectImpl(Quantifier quantifier, Field extends Object[]> array) {
this.quantifier = quantifier;
this.query = null;
this.array = array;
+ this.values = null;
+ }
+
+ QuantifiedSelectImpl(Quantifier quantifier, Field>... values) {
+ this.quantifier = quantifier;
+ this.query = null;
+ this.array = null;
+ this.values = values;
}
@Override
@@ -106,9 +116,20 @@ final class QuantifiedSelectImpl extends AbstractQueryPart imp
}
- private final QueryPartInternal delegate(Configuration ctx) {
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private final QueryPart delegate(Configuration ctx) {
if (query != null) {
- return (QueryPartInternal) query;
+ return query;
+ }
+ else if (values != null) {
+ Select> select = null;
+ for (Field value : values)
+ if (select == null)
+ select = select(value);
+ else
+ select = select.unionAll(select(value));
+
+ return select;
}
else {
switch (ctx.family()) {
@@ -118,14 +139,14 @@ final class QuantifiedSelectImpl extends AbstractQueryPart imp
case POSTGRES: {
- return (QueryPartInternal) array;
+ return array;
}
// [#869] H2 and HSQLDB can emulate this syntax by unnesting
// the array in a subselect
case H2:
case HSQLDB:
- return (QueryPartInternal) create(ctx).select().from(table(array));
+ return create(ctx).select().from(table(array));
// [#1048] All other dialects emulate unnesting of arrays using
// UNION ALL-connected subselects
@@ -134,19 +155,19 @@ final class QuantifiedSelectImpl extends AbstractQueryPart imp
// The Informix database has an interesting bug when quantified comparison predicates
// use nested derived tables with UNION ALL
if (array instanceof Param) {
- Object[] values = ((Param extends Object[]>) array).getValue();
+ Object[] values0 = ((Param extends Object[]>) array).getValue();
Select> select = null;
- for (Object value : values)
+ for (Object value : values0)
if (select == null)
select = select(val(value));
else
select = select.unionAll(select(val(value)));
- return (QueryPartInternal) select;
+ return select;
}
else {
- return (QueryPartInternal) select().from(table(array));
+ return select().from(table(array));
}
}
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/Quantifier.java b/jOOQ/src/main/java/org/jooq/impl/Quantifier.java
index 8e1cdb167d..c946968793 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Quantifier.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Quantifier.java
@@ -37,7 +37,13 @@
*/
package org.jooq.impl;
+import static org.jooq.impl.DSL.all;
+import static org.jooq.impl.DSL.any;
+
import org.jooq.Keyword;
+import org.jooq.QuantifiedSelect;
+import org.jooq.Record;
+import org.jooq.Select;
/**
* A quantifier used for quantified comparison predicates
@@ -73,4 +79,15 @@ enum Quantifier {
public final Keyword toKeyword() {
return keyword;
}
+
+ public QuantifiedSelect apply(Select select) {
+ switch (this) {
+ case ANY:
+ return any(select);
+ case ALL:
+ return all(select);
+ default:
+ throw new IllegalStateException();
+ }
+ }
}