Fix for #85 - Invalid query when ORDER BY with DISTINCT

This commit is contained in:
Rob Bygrave
2014-05-18 23:00:28 +12:00
parent b587aa8172
commit b8743a5ef2
2 changed files with 81 additions and 2 deletions
@@ -305,6 +305,8 @@ public class CQueryBuilder implements Constants {
StringBuilder sb = new StringBuilder(500);
String dbOrderBy = predicates.getDbOrderBy();
if (selectClause != null) {
sb.append(selectClause);
@@ -320,6 +322,10 @@ public class CQueryBuilder implements Constants {
}
sb.append(select.getSelectSql());
if (query.isDistinct() && dbOrderBy != null) {
// add the orderby columns to the select clause (due to distinct)
sb.append(", ").append(convertDbOrderByForSelect(dbOrderBy));
}
}
sb.append(" from ");
@@ -375,7 +381,7 @@ public class CQueryBuilder implements Constants {
sb.append(dbFilterMany);
}
String dbOrderBy = predicates.getDbOrderBy();
if (dbOrderBy != null) {
sb.append(" order by ").append(dbOrderBy);
}
@@ -386,12 +392,20 @@ public class CQueryBuilder implements Constants {
return sqlLimiter.limit(r);
} else {
return new SqlLimitResponse(dbPlatform.completeSql(sb.toString(), query), false);
}
}
/**
* Convert the dbOrderBy clause to be safe for adding to select. This is done when 'distinct' is
* used.
*/
private String convertDbOrderByForSelect(String dbOrderBy) {
// just remove the ASC and DESC keywords
return dbOrderBy.replaceAll("(?i)\\b asc\\b|\\b desc\\b", "");
}
private boolean isEmpty(String s) {
return s == null || s.length() == 0;
}
@@ -0,0 +1,65 @@
package com.avaje.tests.query.orderby;
import org.junit.Assert;
import org.junit.Test;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.Query;
import com.avaje.tests.model.basic.Customer;
public class TestOrderByWithDistinctTake2 extends BaseTestCase {
@Test
public void testRegex() {
String test = "helloasc asc ASC desc DESC boodesc desc ASC";
test = test.replaceAll("(?i)\\b asc\\b|\\b desc\\b", "");
System.out.println(test);
Assert.assertEquals("helloasc boodesc", test);
}
@Test
public void test() {
Query<Customer> query = Ebean.find(Customer.class)
.select("id")
.where().ilike("contacts.firstName", "R%")
.order("name desc");
query.findList();
String generatedSql = query.getGeneratedSql();
// select distinct t0.id c0, t0.name
// from o_customer t0 join contact u1 on u1.customer_id = t0.id
// where lower(u1.first_name) like ?
// order by t0.name; --bind(r%)
Assert.assertTrue("t0.name added to the select clause", generatedSql.contains("select distinct t0.id c0, t0.name"));
Assert.assertTrue(generatedSql.contains("order by t0.name desc"));
Assert.assertTrue(generatedSql.contains("from o_customer t0 join contact u1 on u1.customer_id = t0.id"));
Assert.assertTrue(generatedSql.contains("where lower(u1.first_name) like ?"));
}
@Test
public void testWithAscAndDesc() {
Query<Customer> query = Ebean.find(Customer.class)
.select("id")
.where().ilike("contacts.firstName", "R%")
.order("name asc,id desc");
query.findList();
String generatedSql = query.getGeneratedSql();
Assert.assertTrue("t0.name added to the select clause", generatedSql.contains("select distinct t0.id c0, t0.name, t0.id"));
Assert.assertTrue(generatedSql.contains("order by t0.name, t0.id desc"));
Assert.assertTrue(generatedSql.contains("from o_customer t0 join contact u1 on u1.customer_id = t0.id"));
Assert.assertTrue(generatedSql.contains("where lower(u1.first_name) like ?"));
}
}