Improve building of SQL from an RSQL query (#1766)
* Improve building of SQL from an RSQL query * ignore case behavior could be disabled * like is used only when needed Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com> * Inlining of some methods and unified IN build + fix case Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com> * Implement more flexible ignore case configuration Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com> --------- Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -21,6 +21,7 @@ import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
@@ -43,34 +44,30 @@ public class RSQLActionFieldsTest extends AbstractJpaIntegrationTest {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("daA");
|
||||
target = (JpaTarget) targetManagement
|
||||
.create(entityFactory.target().create().controllerId("targetId123").description("targetId123"));
|
||||
action = new JpaAction();
|
||||
action.setActionType(ActionType.SOFT);
|
||||
action.setDistributionSet(dsA);
|
||||
action.setTarget(target);
|
||||
action.setStatus(Status.RUNNING);
|
||||
action.setWeight(45);
|
||||
action.setInitiatedBy(tenantAware.getCurrentUsername());
|
||||
|
||||
action = newJpaAction(dsA, false, null);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
newJpaAction(dsA, i % 2 == 0, i % 2 == 0 ? "extRef" : "extRef2");
|
||||
}
|
||||
}
|
||||
|
||||
private @NotNull JpaAction newJpaAction(final DistributionSet dsA, final boolean active, final String extRef) {
|
||||
final JpaAction newAction = new JpaAction();
|
||||
newAction.setActionType(ActionType.SOFT);
|
||||
newAction.setDistributionSet(dsA);
|
||||
newAction.setActive(active);
|
||||
newAction.setStatus(Status.RUNNING);
|
||||
newAction.setTarget(target);
|
||||
newAction.setWeight(45);
|
||||
newAction.setInitiatedBy(tenantAware.getCurrentUsername());
|
||||
if (extRef != null) {
|
||||
newAction.setExternalRef(extRef);
|
||||
}
|
||||
actionRepository.save(newAction);
|
||||
|
||||
target.addAction(action);
|
||||
|
||||
actionRepository.save(action);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
final JpaAction newAction = new JpaAction();
|
||||
newAction.setActionType(ActionType.SOFT);
|
||||
newAction.setDistributionSet(dsA);
|
||||
newAction.setActive((i % 2) == 0);
|
||||
newAction.setStatus(Status.RUNNING);
|
||||
newAction.setTarget(target);
|
||||
newAction.setWeight(45);
|
||||
newAction.setInitiatedBy(tenantAware.getCurrentUsername());
|
||||
if ((i % 2) == 0) {
|
||||
newAction.setExternalRef("extRef");
|
||||
} else {
|
||||
newAction.setExternalRef("extRef2");
|
||||
}
|
||||
actionRepository.save(newAction);
|
||||
target.addAction(newAction);
|
||||
}
|
||||
|
||||
return newAction;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -116,11 +113,11 @@ public class RSQLActionFieldsTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
private void assertRSQLQuery(final String rsqlParam, final long expectedEntities) {
|
||||
|
||||
final Slice<Action> findEnitity = deploymentManagement.findActionsByTarget(rsqlParam, target.getControllerId(),
|
||||
final Slice<Action> findEntity = deploymentManagement.findActionsByTarget(rsqlParam, target.getControllerId(),
|
||||
PageRequest.of(0, 100));
|
||||
final long countAllEntities = deploymentManagement.countActionsByTarget(rsqlParam, target.getControllerId());
|
||||
assertThat(findEnitity).isNotNull();
|
||||
assertThat(findEntity).isNotNull();
|
||||
assertThat(findEntity.getContent().size()).isEqualTo(expectedEntities);
|
||||
assertThat(countAllEntities).isEqualTo(expectedEntities);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||
import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder;
|
||||
import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder;
|
||||
import org.eclipse.hawkbit.repository.rsql.RsqlVisitorFactory;
|
||||
import org.eclipse.hawkbit.repository.rsql.RsqlVisitorFactoryHolder;
|
||||
import org.eclipse.hawkbit.repository.rsql.RsqlConfigHolder;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
@@ -116,8 +116,8 @@ public class RSQLUtilityTest {
|
||||
}
|
||||
|
||||
@Bean
|
||||
RsqlVisitorFactoryHolder rsqlVisitorFactoryHolder() {
|
||||
return RsqlVisitorFactoryHolder.getInstance();
|
||||
RsqlConfigHolder rsqlVisitorFactoryHolder() {
|
||||
return RsqlConfigHolder.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,12 +284,36 @@ public class RSQLUtilityTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctRsqlBuildsSimpleNotLikePredicate() {
|
||||
public void correctRsqlBuildsSimpleNotEqualPredicate() {
|
||||
reset(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name!=abc";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
||||
|
||||
when(criteriaBuilderMock.isNull(any(Expression.class))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.notEqual(any(Expression.class), anyString()))
|
||||
.thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock))))
|
||||
.thenReturn(pathOfString(baseSoftwareModuleRootMock));
|
||||
|
||||
// test
|
||||
RSQLUtility.buildRsqlSpecification(correctRsql, SoftwareModuleFields.class, null, testDb)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).or(any(Predicate.class), any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).isNull(eq(pathOfString(baseSoftwareModuleRootMock)));
|
||||
verify(criteriaBuilderMock, times(1)).notEqual(eq(pathOfString(baseSoftwareModuleRootMock)),
|
||||
eq("abc".toUpperCase()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctRsqlBuildsSimpleNotLikePredicate() {
|
||||
reset(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name!=abc*";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
||||
|
||||
when(criteriaBuilderMock.isNull(any(Expression.class))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.notLike(any(Expression.class), anyString(), eq('\\')))
|
||||
.thenReturn(mock(Predicate.class));
|
||||
@@ -304,7 +328,7 @@ public class RSQLUtilityTest {
|
||||
verify(criteriaBuilderMock, times(1)).or(any(Predicate.class), any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).isNull(eq(pathOfString(baseSoftwareModuleRootMock)));
|
||||
verify(criteriaBuilderMock, times(1)).notLike(eq(pathOfString(baseSoftwareModuleRootMock)),
|
||||
eq("abc".toUpperCase()), eq('\\'));
|
||||
eq("abc%".toUpperCase()), eq('\\'));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -335,11 +359,32 @@ public class RSQLUtilityTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctRsqlBuildsLikePredicateWithPercentage() {
|
||||
public void correctRsqlBuildsEqualPredicateWithPercentage() {
|
||||
reset(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name==a%";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
||||
when(criteriaBuilderMock.equal(any(Expression.class), anyString())).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class)))
|
||||
.thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock))))
|
||||
.thenReturn(pathOfString(baseSoftwareModuleRootMock));
|
||||
// test
|
||||
RSQLUtility.buildRsqlSpecification(correctRsql, SoftwareModuleFields.class, null, Database.H2)
|
||||
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).equal(eq(pathOfString(baseSoftwareModuleRootMock)),
|
||||
eq("a%".toUpperCase()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctRsqlBuildsLikePredicateWithPercentage() {
|
||||
reset(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name==a%*";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
||||
when(criteriaBuilderMock.like(any(Expression.class), anyString(), eq('\\'))).thenReturn(mock(Predicate.class));
|
||||
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class)))
|
||||
.thenReturn(mock(Predicate.class));
|
||||
@@ -352,13 +397,13 @@ public class RSQLUtilityTest {
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).like(eq(pathOfString(baseSoftwareModuleRootMock)),
|
||||
eq("a\\%".toUpperCase()), eq('\\'));
|
||||
eq("a\\%%".toUpperCase()), eq('\\'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctRsqlBuildsLikePredicateWithPercentageSQLServer() {
|
||||
reset(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
|
||||
final String correctRsql = "name==a%";
|
||||
final String correctRsql = "name==a%*";
|
||||
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
|
||||
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
|
||||
when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock))))
|
||||
@@ -374,7 +419,7 @@ public class RSQLUtilityTest {
|
||||
// verification
|
||||
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
|
||||
verify(criteriaBuilderMock, times(1)).like(eq(pathOfString(baseSoftwareModuleRootMock)),
|
||||
eq("a[%]".toUpperCase()), eq('\\'));
|
||||
eq("a[%]%".toUpperCase()), eq('\\'));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user