auomatically append "order by id" when paging and query.orderById = true (#1275)

Add ServerConfig.setDefaultOrderById() and query.orderById(boolean) ... to control automatically append "order by id" with paging query
This commit is contained in:
Roland Praml
2018-02-27 10:09:52 +13:00
committed by Rob Bygrave
parent 0cba0664f8
commit a712be2917
11 changed files with 235 additions and 37 deletions
@@ -1,5 +1,6 @@
package io.ebean;
import org.ebeantest.LoggedSqlCollector;
import org.junit.Test;
import org.tests.model.basic.Customer;
import org.tests.model.basic.ResetBasicData;
@@ -8,6 +9,8 @@ import javax.persistence.PersistenceException;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
public class EbeanServer_eqlTest extends BaseTestCase {
@@ -85,6 +88,40 @@ public class EbeanServer_eqlTest extends BaseTestCase {
} else {
assertThat(query.getGeneratedSql()).endsWith("order by t0.name limit 10 offset 3");
}
// check also select count(*)
LoggedSqlCollector.start();
query.findCount();
List<String>sql = LoggedSqlCollector.stop();
assertThat(sql.get(0)).startsWith("select count(*) from o_customer t0;");
}
@Test
public void basic_limit_offset2_with_id() {
ResetBasicData.reset();
Query<Customer> query = Ebean.createQuery(Customer.class, "order by name");
query.setMaxRows(10);
query.setFirstRow(3);
query.orderById(true);
query.findList();
if (isSqlServer()) {
assertThat(query.getGeneratedSql()).endsWith("order by t0.name, t0.id offset 3 rows fetch next 10 rows only");
} else if (isOracle()) {
assertThat(query.getGeneratedSql()).contains("where rownum <= 13");
assertThat(query.getGeneratedSql()).contains("where rn_ > 3");
} else {
assertThat(query.getGeneratedSql()).endsWith("order by t0.name, t0.id limit 10 offset 3");
}
// check also select count(*)
LoggedSqlCollector.start();
query.findCount();
List<String>sql = LoggedSqlCollector.stop();
assertThat(sql.get(0)).startsWith("select count(*) from o_customer t0;");
}
@Test
@@ -37,6 +37,32 @@ public class TestOrderByWithDistinct extends BaseTestCase {
}
@Test
public void testOrderByWithDistinct() {
Query<MUser> query = Ebean.find(MUser.class);
query.findList();
assertThat(query.getGeneratedSql()).doesNotContain("order by");
assertThat(query.getGeneratedSql()).doesNotContain("select distinct");
query.setMaxRows(1000);
query.findList();
assertThat(query.getGeneratedSql()).contains("order by t0.userid");
query = Ebean.find(MUser.class)
.where()
.eq("roles.roleName", "A")
.query();
query.findList();
assertThat(query.getGeneratedSql()).doesNotContain("order by");
assertThat(query.getGeneratedSql()).contains("select distinct");
query.setMaxRows(1000);
query.findList();
assertThat(query.getGeneratedSql()).contains("order by t0.userid");
}
@Test
public void test() {
/*
@@ -244,11 +244,11 @@ public class TestQuerySingleAttribute extends BaseTestCase {
List<String> ids = query.findSingleAttributeList();
if (isSqlServer()) {
assertThat(sqlOf(query)).contains("select top 100 t0.id from o_customer t0");
assertThat(sqlOf(query)).contains("select top 100 t0.id from o_customer t0 order by t0.id");
} else if (isOracle()) {
assertThat(sqlOf(query)).contains("where rownum <= 100");
} else {
assertThat(sqlOf(query)).contains("select t0.id from o_customer t0 limit 100");
assertThat(sqlOf(query)).contains("select t0.id from o_customer t0 order by t0.id limit 100");
}
assertThat(ids).isNotEmpty();
}
@@ -10,6 +10,8 @@ import io.ebean.RawSql;
import io.ebean.RawSqlBuilder;
import io.ebean.annotation.IgnorePlatform;
import io.ebean.annotation.Platform;
import org.ebeantest.LoggedSqlCollector;
import org.junit.Assert;
import org.junit.Test;
import org.tests.model.basic.Customer;
@@ -67,6 +69,13 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
List<Customer> list = query.findList();
Assert.assertNotNull(list);
// check also select count(*)
LoggedSqlCollector.start();
assertThat(query.findCount()).isEqualTo(list.size());
List<String>sql = LoggedSqlCollector.stop();
assertThat(sql.get(0)).startsWith("select count(*) from ( select r.id, r.name from o_customer r");
assertThat(sql.get(0)).doesNotContain("order by");
}
@Test
@@ -104,7 +113,6 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
query.setFirstRow(1);
query.setMaxRows(2);
query.order().asc("id");
List<Customer> list = query.findList();
@@ -170,12 +178,54 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
if (isSqlServer()) {
assertThat(query.getGeneratedSql()).contains("top 100 ");
assertThat(query.getGeneratedSql()).contains("order by o.ship_date desc");
assertThat(query.getGeneratedSql()).contains("order by o.ship_date desc ");
} else if (isOracle()) {
assertThat(query.getGeneratedSql()).contains("a where rownum <= 100 )");
} else {
assertThat(query.getGeneratedSql()).contains("order by o.ship_date desc limit 100");
}
// check also select count(*)
LoggedSqlCollector.start();
query.findCount();
List<String>sql = LoggedSqlCollector.stop();
assertThat(sql.get(0)).startsWith("select count(*) from ( select o.id, o.order_date, o.ship_date from o_order o");
assertThat(sql.get(0)).doesNotContain("order by");
}
@Test
public void testPaging_with_existingRawSqlOrderBy_expect_id_appendToOrderBy_with_id() {
ResetBasicData.reset();
RawSql rawSql = RawSqlBuilder.parse("select o.id, o.order_date, o.ship_date from o_order o order by o.ship_date desc")
.columnMapping("o.id", "id")
.columnMapping("o.order_date", "orderDate")
.columnMapping("o.ship_date", "shipDate")
.create();
Query<Order> query = Ebean.find(Order.class);
query.setRawSql(rawSql);
query.orderById(true);
query.setMaxRows(100);
query.findList();
if (isSqlServer()) {
assertThat(query.getGeneratedSql()).contains("top 100 ");
assertThat(query.getGeneratedSql()).contains("order by o.ship_date desc, o.id ");
} else if (isOracle()) {
assertThat(query.getGeneratedSql()).contains("a where rownum <= 100 )");
} else {
assertThat(query.getGeneratedSql()).contains("order by o.ship_date desc, o.id limit 100");
}
// check also select count(*)
LoggedSqlCollector.start();
query.findCount();
List<String>sql = LoggedSqlCollector.stop();
assertThat(sql.get(0)).startsWith("select count(*) from ( select o.id, o.order_date, o.ship_date from o_order o");
assertThat(sql.get(0)).doesNotContain("order by");
}
@IgnorePlatform(Platform.ORACLE)
@@ -199,7 +249,7 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
query.order("coalesce(shipDate, getdate()) desc");
query.findList();
assertThat(sqlOf(query)).contains("order by coalesce(o.ship_date, getdate()) desc");
assertThat(sqlOf(query)).contains("order by coalesce(o.ship_date, getdate()) desc ");
assertThat(sqlOf(query)).contains("select top 100");
} else {
@@ -210,6 +260,39 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
}
}
@IgnorePlatform(Platform.ORACLE)
@Test
public void testPaging_when_setOrderBy_expect_id_appendToOrderBy_with_id() {
ResetBasicData.reset();
RawSql rawSql = RawSqlBuilder.parse("select o.id, o.order_date, o.ship_date from o_order o order by o.ship_date desc nulls last")
.columnMapping("o.id", "id")
.columnMapping("o.order_date", "orderDate")
.columnMapping("o.ship_date", "shipDate")
.create();
Query<Order> query = Ebean.find(Order.class);
query.setRawSql(rawSql);
query.setMaxRows(100);
query.orderById(true);
if (isSqlServer()) {
query.order("coalesce(shipDate, getdate()) desc");
query.findList();
assertThat(sqlOf(query)).contains("order by coalesce(o.ship_date, getdate()) desc, o.id");
assertThat(sqlOf(query)).contains("select top 100");
} else {
query.order("coalesce(shipDate, now()) desc");
query.findList();
assertThat(query.getGeneratedSql()).contains("order by coalesce(o.ship_date, now()) desc, o.id limit 100");
}
}
@Test
public void testPaging_when_setOrderBy_containsId_expect_leaveAsIs() {
@@ -13,7 +13,7 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
@ForPlatform(Platform.H2)
@Test
public void h2Merge() {
public void h2Merge() throws InterruptedException {
String sql = "merge into e_person_online (email, online_status, when_updated) key(email) values (?, ?, now())";
@@ -30,6 +30,7 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
assertThat(found.getEmail()).isEqualTo(email);
assertThat(found.isOnlineStatus()).isTrue();
Thread.sleep(50); // have to wait some millis here
String sqlNamed = "merge into e_person_online (email, online_status, when_updated) key(email) values (:email, :online, now())";
SqlUpdate sqlUpdate2 = Ebean.createSqlUpdate(sqlNamed)
@@ -46,7 +47,7 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
assertThat(found2.getId()).isEqualTo(key);
assertThat(found2.getEmail()).isEqualTo(email);
assertThat(found2.isOnlineStatus()).isFalse();
assertThat(found2.getWhenUpdated()).isGreaterThan(found.getWhenUpdated());
assertThat(found2.getWhenUpdated()).isGreaterThan(found.getWhenUpdated()); // otherwise this test fails on my machine
}
@ForPlatform(Platform.POSTGRES)