Add test for soft deleted children

When a child is referenced in the query, Ebean should make sure
that the child (or any of the objects connecting it in the query)
is deleted.

Ie. if a query requires a child to have a certain value, it should
filter out those children that are soft deleted. It should also perform
the deleted check on all objects leading up to that child.

E.g. assuming that all objects are soft deletable, the following where():

DB.find(Alpha.class).where()
.eq("alpha.beta.gamma.name", "bar")

should generate a query with
"t0.deleted = false AND t1.deleted = false AND t2.deleted = false AND t2.name = 'bar'"
This commit is contained in:
Tobias
2020-07-07 12:33:43 +02:00
parent 361de9ea99
commit e99db44ddf
@@ -9,11 +9,13 @@ import io.ebean.SqlRow;
import io.ebean.Transaction;
import org.ebeantest.LoggedSqlCollector;
import org.junit.Test;
import org.tests.model.softdelete.EBasicNoSDChild;
import org.tests.model.softdelete.EBasicSDChild;
import org.tests.model.softdelete.EBasicSoftDelete;
import java.util.List;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
@@ -136,6 +138,64 @@ public class TestSoftDeleteBasic extends BaseTestCase {
query.delete();
}
@Test
public void testNotFindSoftDeleted() {
EBasicSoftDelete bean = new EBasicSoftDelete();
bean.setName("Shouldn't be found with child expression when child is deleted");
DB.save(bean);
final EBasicSDChild child = new EBasicSDChild(bean, "Delete me, don't find me", 1L);
DB.save(child);
DB.delete(child);
Query<EBasicSoftDelete> query = DB.find(EBasicSoftDelete.class)
.where()
.eq("id", bean.getId())
.eq("children.amount", 1L)
.query();
List<EBasicSoftDelete> list = query.findList();
assertSql(query).contains("t0.deleted = false");
// Make sure that query includes that the child mustn't've been deleted
assertSql(query).contains("t1.deleted = false");
assertThat(list).hasSize(0);
// Cleanup created entity
query.delete();
DB.deleteAllPermanent(singletonList(child));
DB.deleteAllPermanent(singletonList(bean));
}
@Test
public void testNotFindSoftDeletedMultilevel() {
EBasicSoftDelete bean = new EBasicSoftDelete();
bean.setName("Shouldn't be found with child expression when child is deleted");
DB.save(bean);
final EBasicSDChild child = new EBasicSDChild(bean, "Delete me, don't find me", 1L);
DB.save(child);
DB.delete(child);
EBasicNoSDChild secondChild = new EBasicNoSDChild(bean, "Never deleted", 2L);
DB.save(secondChild);
Query<EBasicNoSDChild> query = DB.find(EBasicNoSDChild.class)
.where()
.eq("id", bean.getId())
.eq("owner.children.amount", 1L)
.query();
List<EBasicNoSDChild> list = query.findList();
// Make sure that query includes that the child mustn't've been deleted
assertSql(query).contains("t1.deleted = false");
assertSql(query).contains("t2.deleted = false");
assertThat(list).hasSize(0);
// Cleanup created entity
query.delete();
DB.deleteAllPermanent(singletonList(child));
DB.deleteAllPermanent(singletonList(bean));
}
@Test
public void testDeleteById_and_findCount() {