diff --git a/src/main/java/com/avaje/ebeaninternal/server/grammer/EqlAdapter.java b/src/main/java/com/avaje/ebeaninternal/server/grammer/EqlAdapter.java index 7a476f114..1eceaf120 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/grammer/EqlAdapter.java +++ b/src/main/java/com/avaje/ebeaninternal/server/grammer/EqlAdapter.java @@ -287,19 +287,38 @@ class EqlAdapter extends EQLBaseListener { if (childCount < 3) { throw new IllegalStateException("expecting 3 children for comparison? " + ctx); } - String path = getLeftHandSidePath(ctx); - String child = child(ctx, 2); - if (path.equals(child)) { - throw new IllegalArgumentException("Invalid expression "+path+" must be on LHS of expression"); - } String operator = child(ctx, 1); EqlOperator op = operatorMapping.get(operator); if (op == null) { throw new IllegalStateException("No operator found for " + operator); } + String path = getLeftHandSidePath(ctx); + String rhs = child(ctx, 2); + if (path.equals(rhs)) { + // the 'value operator path' form + // invert the operator and use LHS as RHS + op = invert(op); + rhs = child(ctx, 0); + } // RHS is Path, Literal or Named input parameter - helper.addExpression(path, op, child); + helper.addExpression(path, op, rhs); + } + + private EqlOperator invert(EqlOperator op) { + switch (op) { + // no change + case EQ : return EqlOperator.EQ; + case IEQ : return EqlOperator.IEQ; + case NE : return EqlOperator.NE; + // invert + case LT : return EqlOperator.GT; + case LTE : return EqlOperator.GTE; + case GT : return EqlOperator.LT; + case GTE : return EqlOperator.LTE; + default: + throw new IllegalStateException("Can not invert operator "+op); + } } diff --git a/src/test/java/com/avaje/ebeaninternal/server/grammer/EqlParserTest.java b/src/test/java/com/avaje/ebeaninternal/server/grammer/EqlParserTest.java index e202e7c6c..f9c12cfeb 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/grammer/EqlParserTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/grammer/EqlParserTest.java @@ -30,6 +30,47 @@ public class EqlParserTest extends BaseTestCase { assertThat(query.getGeneratedSql()).contains("where t0.name = ?"); } + @Test + public void where_eq_reverse() throws Exception { + + Query query = parse("where 'Rob' eq name"); + query.findList(); + + assertThat(query.getGeneratedSql()).contains("where t0.name = ?"); + } + + @Test + public void where_gt_reverse() throws Exception { + + Query query = parse("where 'Rob' > name"); + query.findList(); + assertThat(query.getGeneratedSql()).contains("where t0.name < ?"); + } + + @Test + public void where_gte_reverse() throws Exception { + + Query query = parse("where 'Rob' >= name"); + query.findList(); + assertThat(query.getGeneratedSql()).contains("where t0.name <= ?"); + } + + @Test + public void where_lt_reverse() throws Exception { + + Query query = parse("where 'Rob' < name"); + query.findList(); + assertThat(query.getGeneratedSql()).contains("where t0.name > ?"); + } + + @Test + public void where_lte_reverse() throws Exception { + + Query query = parse("where 'Rob' <= name"); + query.findList(); + assertThat(query.getGeneratedSql()).contains("where t0.name >= ?"); + } + @Test public void where_ieq() throws Exception { @@ -39,6 +80,14 @@ public class EqlParserTest extends BaseTestCase { assertThat(query.getGeneratedSql()).contains("where lower(t0.name) =?"); } + @Test + public void where_ieq_reverse() throws Exception { + + Query query = parse("where 'Rob' ieq name"); + query.findList(); + assertThat(query.getGeneratedSql()).contains("where lower(t0.name) =?"); + } + @Test public void where_eq2() throws Exception { @@ -58,9 +107,13 @@ public class EqlParserTest extends BaseTestCase { assertThat(query.getGeneratedSql()).contains("where t0.name = ?"); } - @Test(expected = IllegalArgumentException.class) + @Test public void where_namedParam_otherOrder() { - parse("where :name < plannedEnd"); + Query query = parse("where :nm < name"); + query.setParameter("nm", "Rob"); + query.findList(); + + assertThat(query.getGeneratedSql()).contains("where t0.name > ?"); } @Test