[jOOQ/jOOQ#8577] Add Field#likeAny() and #notLikeAll()
(work by @knutwannheden)
This commit is contained in:
parent
c5c8d1d256
commit
1fbc546b4a
@ -1627,6 +1627,68 @@ extends
|
||||
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
|
||||
Condition notLikeIgnoreCase(String value, char escape);
|
||||
|
||||
/**
|
||||
* Create a condition to pattern-check this field against any element in an array of values.
|
||||
* <p>
|
||||
* SQL: <code>(this like value0 or this like value1 or ...)</code>
|
||||
*
|
||||
* @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.
|
||||
* <p>
|
||||
* SQL: <code>(this like field0 or this like field1 or ...)</code>
|
||||
*
|
||||
* @see LikeEscapeStep#escape(char)
|
||||
*/
|
||||
@Support
|
||||
@SuppressWarnings("unchecked")
|
||||
LikeEscapeStep likeAny(Field<String>... fields);
|
||||
|
||||
/**
|
||||
* Create a condition to pattern-check this field against any element in a collection of fields or values.
|
||||
* <p>
|
||||
* SQL: <code>(this like field0 or this like field1 or ...)</code>
|
||||
*
|
||||
* @see LikeEscapeStep#escape(char)
|
||||
*/
|
||||
@Support
|
||||
LikeEscapeStep likeAny(Collection<?> values);
|
||||
|
||||
/**
|
||||
* Create a condition to pattern-check this field against all elements in an array of values.
|
||||
* <p>
|
||||
* SQL: <code>(this not like value0 and this not like value1 and ...)</code>
|
||||
*
|
||||
* @see LikeEscapeStep#escape(char)
|
||||
*/
|
||||
@Support
|
||||
LikeEscapeStep notLikeAll(String... values);
|
||||
|
||||
/**
|
||||
* Create a condition to pattern-check this field against all elements in an array of fields.
|
||||
* <p>
|
||||
* SQL: <code>(this not like field0 and this not like field1 and ...)</code>
|
||||
*
|
||||
* @see LikeEscapeStep#escape(char)
|
||||
*/
|
||||
@Support
|
||||
@SuppressWarnings("unchecked")
|
||||
LikeEscapeStep notLikeAll(Field<String>... fields);
|
||||
|
||||
/**
|
||||
* Create a condition to pattern-check this field against all elements in a collection of fields or values.
|
||||
* <p>
|
||||
* SQL: <code>(this not like field0 and this not like field1 and ...)</code>
|
||||
*
|
||||
* @see LikeEscapeStep#escape(char)
|
||||
*/
|
||||
@Support
|
||||
LikeEscapeStep notLikeAll(Collection<?> values);
|
||||
|
||||
/**
|
||||
* Convenience method for {@link #like(String, char)} including proper
|
||||
* adding of wildcards and escaping.
|
||||
|
||||
@ -852,6 +852,40 @@ abstract class AbstractField<T> extends AbstractNamed implements Field<T> {
|
||||
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<String>... fields) {
|
||||
return likeAny(Arrays.asList(fields));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final LikeEscapeStep likeAny(Collection<?> values) {
|
||||
return new CombinedCompareCondition(this, LIKE, Quantifier.ANY, (Collection<? extends Field<String>>) 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<String>... fields) {
|
||||
return notLikeAll(Arrays.asList(fields));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final LikeEscapeStep notLikeAll(Collection<?> values) {
|
||||
return new CombinedCompareCondition(this, NOT_LIKE, Quantifier.ALL, (Collection<? extends Field<String>>) Tools.fields(values, SQLDataType.VARCHAR));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition notLikeRegex(String pattern) {
|
||||
return likeRegex(pattern).not();
|
||||
|
||||
116
jOOQ/src/main/java/org/jooq/impl/CombinedCompareCondition.java
Normal file
116
jOOQ/src/main/java/org/jooq/impl/CombinedCompareCondition.java
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jooq.Comparator;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.LikeEscapeStep;
|
||||
import org.jooq.Operator;
|
||||
|
||||
final class CombinedCompareCondition extends AbstractCondition implements LikeEscapeStep {
|
||||
|
||||
private static final long serialVersionUID = 1850816878293293314L;
|
||||
|
||||
private final Field<?> field;
|
||||
private final Comparator comparator;
|
||||
private final Quantifier quantifier;
|
||||
private final Collection<? extends Field<String>> values;
|
||||
private Character escape;
|
||||
|
||||
public CombinedCompareCondition(Field<?> field, Comparator comparator, Quantifier quantifier, Collection<? extends Field<String>> values) {
|
||||
this.field = field;
|
||||
this.comparator = comparator;
|
||||
this.quantifier = quantifier;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Condition escape(char c) {
|
||||
this.escape = c;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
Collection<Condition> conditions = new ArrayList<Condition>();
|
||||
|
||||
switch (comparator) {
|
||||
case LIKE:
|
||||
for (Field<String> value : values)
|
||||
conditions.add(escape != null ? field.like(value, escape) : field.like(value));
|
||||
break;
|
||||
|
||||
case NOT_LIKE:
|
||||
for (Field<String> value : values)
|
||||
conditions.add(escape != null ? field.notLike(value, escape) : field.notLike(value));
|
||||
break;
|
||||
|
||||
case SIMILAR_TO:
|
||||
for (Field<String> value : values)
|
||||
conditions.add(escape != null ? field.similarTo(value, escape) : field.similarTo(value));
|
||||
break;
|
||||
|
||||
case NOT_SIMILAR_TO:
|
||||
for (Field<String> value : values)
|
||||
conditions.add(escape != null ? field.notSimilarTo(value, escape) : field.notSimilarTo(value));
|
||||
break;
|
||||
|
||||
case LIKE_IGNORE_CASE:
|
||||
for (Field<String> value : values)
|
||||
conditions.add(escape != null ? field.likeIgnoreCase(value, escape) : field.likeIgnoreCase(value));
|
||||
break;
|
||||
|
||||
case NOT_LIKE_IGNORE_CASE:
|
||||
for (Field<String> value : values)
|
||||
conditions.add(escape != null ? field.notLikeIgnoreCase(value, escape) : field.notLikeIgnoreCase(value));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Condition combinedCondition = CombinedCondition.of(quantifier == Quantifier.ALL ? Operator.AND : Operator.OR, conditions);
|
||||
ctx.visit(combinedCondition);
|
||||
}
|
||||
|
||||
}
|
||||
@ -400,6 +400,7 @@ import org.jooq.InsertValuesStepN;
|
||||
import org.jooq.JoinType;
|
||||
import org.jooq.Keyword;
|
||||
// ...
|
||||
import org.jooq.LikeEscapeStep;
|
||||
// ...
|
||||
import org.jooq.Merge;
|
||||
import org.jooq.MergeFinalStep;
|
||||
@ -4388,16 +4389,54 @@ final class ParserImpl implements Parser {
|
||||
: ((RowN) left).between((RowN) r1, (RowN) r2);
|
||||
}
|
||||
else if (left instanceof Field && parseKeywordIf(ctx, "LIKE")) {
|
||||
Field right = toField(ctx, parseConcat(ctx, null));
|
||||
boolean escape = parseKeywordIf(ctx, "ESCAPE");
|
||||
char character = escape ? parseCharacterLiteral(ctx) : ' ';
|
||||
return escape
|
||||
? not
|
||||
? ((Field) left).notLike(right, character)
|
||||
: ((Field) left).like(right, character)
|
||||
: not
|
||||
? ((Field) left).notLike(right)
|
||||
: ((Field) left).like(right);
|
||||
if (!not && parseKeywordIf(ctx, "ANY")) {
|
||||
parse(ctx, '(');
|
||||
List<Field<?>> fields = null;
|
||||
if (parseIf(ctx, ')'))
|
||||
fields = Collections.<Field<?>> emptyList();
|
||||
else {
|
||||
fields = new ArrayList<Field<?>>();
|
||||
do {
|
||||
fields.add(toField(ctx, parseConcat(ctx, null)));
|
||||
}
|
||||
while (parseIf(ctx, ','));
|
||||
parse(ctx, ')');
|
||||
}
|
||||
boolean escape = parseKeywordIf(ctx, "ESCAPE");
|
||||
char character = escape ? parseCharacterLiteral(ctx) : ' ';
|
||||
LikeEscapeStep result = ((Field) left).likeAny(fields);
|
||||
return escape ? result.escape(character) : result;
|
||||
}
|
||||
else if (not && parseKeywordIf(ctx, "ALL")) {
|
||||
parse(ctx, '(');
|
||||
List<Field<?>> fields = null;
|
||||
if (parseIf(ctx, ')'))
|
||||
fields = Collections.<Field<?>> emptyList();
|
||||
else {
|
||||
fields = new ArrayList<Field<?>>();
|
||||
do {
|
||||
fields.add(toField(ctx, parseConcat(ctx, null)));
|
||||
}
|
||||
while (parseIf(ctx, ','));
|
||||
parse(ctx, ')');
|
||||
}
|
||||
boolean escape = parseKeywordIf(ctx, "ESCAPE");
|
||||
char character = escape ? parseCharacterLiteral(ctx) : ' ';
|
||||
LikeEscapeStep result = ((Field) left).notLikeAll(fields);
|
||||
return escape ? result.escape(character) : result;
|
||||
}
|
||||
else {
|
||||
Field right = toField(ctx, parseConcat(ctx, null));
|
||||
boolean escape = parseKeywordIf(ctx, "ESCAPE");
|
||||
char character = escape ? parseCharacterLiteral(ctx) : ' ';
|
||||
return escape
|
||||
? not
|
||||
? ((Field) left).notLike(right, character)
|
||||
: ((Field) left).like(right, character)
|
||||
: not
|
||||
? ((Field) left).notLike(right)
|
||||
: ((Field) left).like(right);
|
||||
}
|
||||
}
|
||||
else if (left instanceof Field && parseKeywordIf(ctx, "ILIKE")) {
|
||||
Field right = toField(ctx, parseConcat(ctx, null));
|
||||
@ -6128,6 +6167,7 @@ final class ParserImpl implements Parser {
|
||||
|
||||
|
||||
|
||||
|
||||
default:
|
||||
Field<?> base = toField(ctx, parseNumericOp(ctx, N));
|
||||
parse(ctx, ',');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user