relational query: Limit the max level to break the infinite loop when circles appear in relation graph
This commit is contained in:
parent
99476c78c9
commit
e4f8c7e878
@ -223,6 +223,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
|
||||
private static final String SELECT_API_USAGE_STATE = "(select aus.id, aus.created_time, aus.tenant_id, aus.entity_id, " +
|
||||
"coalesce((select title from tenant where id = aus.entity_id), (select title from customer where id = aus.entity_id)) as name " +
|
||||
"from api_usage_state as aus)";
|
||||
static final int MAX_LEVEL_DEFAULT = 10; //This value has to be reasonable small to prevent infinite recursion as early as possible
|
||||
|
||||
static {
|
||||
entityTableMap.put(EntityType.ASSET, "asset");
|
||||
@ -704,8 +705,12 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
|
||||
return whereFilter.toString();
|
||||
}
|
||||
|
||||
private String getLvlFilter(int maxLevel) {
|
||||
return maxLevel > 0 ? ("and lvl <= " + (maxLevel - 1)) : "";
|
||||
String getLvlFilter(int maxLevel) {
|
||||
return "and re.lvl <= " + (getMaxLevel(maxLevel) - 1);
|
||||
}
|
||||
|
||||
int getMaxLevel(int maxLevel) {
|
||||
return maxLevel > 0 ? maxLevel : MAX_LEVEL_DEFAULT;
|
||||
}
|
||||
|
||||
private String getQueryTemplate(EntitySearchDirection direction) {
|
||||
|
||||
@ -568,9 +568,9 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest {
|
||||
|
||||
createManyCustomRelationsBetweenTwoNodes(tenantId, "UseCase", assets, devices);
|
||||
createHorizontalRingRelations(tenantId, "Ring(Loop)-Ast", assets);
|
||||
//createLoopRelations(tenantId, "Loop-Tnt-Ast-Dev", tenantId, assets.get(0).getId(), devices.get(0).getId());
|
||||
//createLoopRelations(tenantId, "Loop-Tnt-Ast", tenantId, assets.get(1).getId());
|
||||
//createLoopRelations(tenantId, "Loop-Ast-Tnt-Ast", assets.get(2).getId(), tenantId, assets.get(3).getId());
|
||||
createLoopRelations(tenantId, "Loop-Tnt-Ast-Dev", tenantId, assets.get(0).getId(), devices.get(0).getId());
|
||||
createLoopRelations(tenantId, "Loop-Tnt-Ast", tenantId, assets.get(1).getId());
|
||||
createLoopRelations(tenantId, "Loop-Ast-Tnt-Ast", assets.get(2).getId(), tenantId, assets.get(3).getId());
|
||||
}
|
||||
|
||||
void createLoopRelations(TenantId tenantId, String type, EntityId... ids) {
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package org.thingsboard.server.dao.sql.query;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.BDDMockito.willCallRealMethod;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class DefaultEntityQueryRepositoryTest {
|
||||
|
||||
/*
|
||||
* This value has to be reasonable small to prevent infinite recursion as early as possible
|
||||
* */
|
||||
@Test
|
||||
public void givenDefaultMaxLevel_whenStaticConstant_thenEqualsTo() {
|
||||
assertThat(DefaultEntityQueryRepository.MAX_LEVEL_DEFAULT, equalTo(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMaxLevelZeroOrNegative_whenGetMaxLevel_thenReturnDefaultMaxLevel() {
|
||||
DefaultEntityQueryRepository repo = mock(DefaultEntityQueryRepository.class);
|
||||
willCallRealMethod().given(repo).getMaxLevel(anyInt());
|
||||
assertThat(repo.getMaxLevel(0), equalTo(DefaultEntityQueryRepository.MAX_LEVEL_DEFAULT));
|
||||
assertThat(repo.getMaxLevel(-1), equalTo(DefaultEntityQueryRepository.MAX_LEVEL_DEFAULT));
|
||||
assertThat(repo.getMaxLevel(-2), equalTo(DefaultEntityQueryRepository.MAX_LEVEL_DEFAULT));
|
||||
assertThat(repo.getMaxLevel(Integer.MIN_VALUE), equalTo(DefaultEntityQueryRepository.MAX_LEVEL_DEFAULT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMaxLevelPositive_whenGetMaxLevel_thenValueTheSame() {
|
||||
DefaultEntityQueryRepository repo = mock(DefaultEntityQueryRepository.class);
|
||||
willCallRealMethod().given(repo).getMaxLevel(anyInt());
|
||||
assertThat(repo.getMaxLevel(1), equalTo(1));
|
||||
assertThat(repo.getMaxLevel(2), equalTo(2));
|
||||
assertThat(repo.getMaxLevel(Integer.MAX_VALUE), equalTo(Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user