further improved like->regex handling

This commit is contained in:
Timo Westkämper 2012-07-13 13:58:10 +03:00
parent 78b5f2a198
commit 08080284d4
4 changed files with 27 additions and 13 deletions

View File

@ -231,30 +231,38 @@ public final class ExpressionUtils {
return new PredicateOperation(Ops.IS_NOT_NULL, left);
}
/**
* Convert the given like pattern to a regex pattern
*
* @param expr
* @return
*/
@SuppressWarnings("unchecked")
*/
public static Expression<String> likeToRegex(Expression<String> expr){
return likeToRegex(expr, true);
}
@SuppressWarnings("unchecked")
public static Expression<String> likeToRegex(Expression<String> expr, boolean matchStartAndEnd){
// TODO : this should take the escape character into account
if (expr instanceof Constant<?>) {
String like = expr.toString();
if (!like.startsWith("%") && !like.startsWith("_")) {
like = "^" + like;
}
if (!like.endsWith("%") && !like.endsWith("_")) {
like = like + "$";
}
like = like.replace("%", ".*").replace("_", ".");
if (matchStartAndEnd) {
if (!like.startsWith("%")) {
like = "^" + like;
}
if (!like.endsWith("%")) {
like = like + "$";
}
}
like = like.replace(".", "\\.").replace("%", ".*").replace("_", ".");
return ConstantImpl.create(like);
} else if (expr instanceof Operation<?>) {
Operation<?> o = (Operation<?>)expr;
if (o.getOperator() == Ops.CONCAT) {
Expression<String> lhs = likeToRegex((Expression<String>) o.getArg(0));
Expression<String> rhs = likeToRegex((Expression<String>) o.getArg(1));
Expression<String> lhs = likeToRegex((Expression<String>) o.getArg(0), false);
Expression<String> rhs = likeToRegex((Expression<String>) o.getArg(1), false);
return new OperationImpl<String>(String.class, Ops.CONCAT, lhs, rhs);
} else {
return expr;

View File

@ -32,7 +32,7 @@ public class ExpressionUtilsTest {
assertEquals(".*", regex(ConstantImpl.create("%")));
assertEquals("^abc.*", regex(ConstantImpl.create("abc%")));
assertEquals(".*abc$", regex(ConstantImpl.create("%abc")));
assertEquals(".", regex(ConstantImpl.create("_")));
assertEquals("^.$", regex(ConstantImpl.create("_")));
StringPath path = new StringPath("path");
assertEquals("path + .*", regex(path.append("%")));
@ -41,6 +41,11 @@ public class ExpressionUtilsTest {
assertEquals(". + path", regex(path.prepend("_")));
}
@Test
public void LikeToRegex_Escape() {
assertEquals("^\\.$", regex(ConstantImpl.create(".")));
}
@Test
public void RegexToLike() {
assertEquals("%", like(ConstantImpl.create(".*")));

View File

@ -331,7 +331,7 @@ public final class JDOQLSerializer extends SerializerBase<JDOQLSerializer> {
} else if (operator.equals(Ops.LIKE) || operator.equals(Ops.LIKE_ESCAPE)) {
super.visitOperation(type, Ops.MATCHES,
Arrays.asList(args.get(0), ExpressionUtils.likeToRegex((Expression<String>) args.get(1))));
Arrays.asList(args.get(0), ExpressionUtils.likeToRegex((Expression<String>) args.get(1), false)));
// exists
} else if (operator.equals(Ops.EXISTS) && args.get(0) instanceof SubQueryExpression) {

View File

@ -239,6 +239,7 @@ public class MongodbQueryTest {
@Test
public void Like() {
assertQuery(user.firstName.like("Jaan"));
assertQuery(user.firstName.like("Jaan%"), u3, u4);
assertQuery(user.firstName.like("jaan%"));