diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/RsqlConfigHolder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/RsqlConfigHolder.java
new file mode 100644
index 000000000..5795f9743
--- /dev/null
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/RsqlConfigHolder.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2021 Bosch.IO GmbH and others
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.eclipse.hawkbit.repository.rsql;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+
+/**
+ * Helper class providing static access to the RSQL configuration as managed the ignoreCase and
+ * the {@link RsqlVisitorFactory} bean.
+ */
+@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE)
+@Getter
+public final class RsqlConfigHolder {
+
+ private static final RsqlConfigHolder SINGLETON = new RsqlConfigHolder();
+
+ /**
+ * If RSQL comparison operators shall ignore the case. If ignore case is true
+ * "x == ax" will match "x == aX"
+ */
+ @Value("${hawkbit.rsql.ignoreCase:true}")
+ private boolean ignoreCase;
+ /**
+ * Declares if the database is case-insensitive, by default assumes false. In case it is case-sensitive and,
+ * {@link #ignoreCase} is set to true the SQL queries use upper case comparisons to ignore case.
+ *
+ * If the database is declared as case-sensitive and ignoreCase is set to false the RSQL queries shall use strict
+ * syntax - i.e. 'and' instead of 'AND' / 'aND'. Otherwise, the queries would be case-insensitive regarding operators.
+ */
+ @Value("${hawkbit.rsql.caseInsensitiveDB:false}")
+ private boolean caseInsensitiveDB;
+ @Autowired
+ private RsqlVisitorFactory rsqlVisitorFactory;
+
+ /**
+ * @return The holder singleton instance.
+ */
+ public static RsqlConfigHolder getInstance() {
+ return SINGLETON;
+ }
+}
\ No newline at end of file
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/RsqlVisitorFactoryHolder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/RsqlVisitorFactoryHolder.java
deleted file mode 100644
index 2b108b00e..000000000
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/rsql/RsqlVisitorFactoryHolder.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (c) 2021 Bosch.IO GmbH and others
- *
- * This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.eclipse.hawkbit.repository.rsql;
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-/**
- * Helper class providing static access to the managed
- * {@link RsqlVisitorFactory} bean.
- */
-public final class RsqlVisitorFactoryHolder {
-
- private static final RsqlVisitorFactoryHolder SINGLETON = new RsqlVisitorFactoryHolder();
-
- @Autowired
- private RsqlVisitorFactory rsqlVisitorFactory;
-
- private RsqlVisitorFactoryHolder() {
-
- }
-
- /**
- * @return The holder singleton instance.
- */
- public static RsqlVisitorFactoryHolder getInstance() {
- return SINGLETON;
- }
-
- /**
- * @return The managed RsqlVisitorFactory bean
- */
- public RsqlVisitorFactory getRsqlVisitorFactory() {
- return rsqlVisitorFactory;
- }
-
-}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java
index 2d2689668..cbfffe743 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java
@@ -157,7 +157,7 @@ import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder;
import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder;
import org.eclipse.hawkbit.repository.rsql.RsqlValidationOracle;
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.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
@@ -1016,13 +1016,13 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
}
/**
- * Obtains the {@link RsqlVisitorFactoryHolder} bean.
+ * Obtains the {@link RsqlConfigHolder} bean.
*
- * @return The {@link RsqlVisitorFactoryHolder} singleton.
+ * @return The {@link RsqlConfigHolder} singleton.
*/
@Bean
- RsqlVisitorFactoryHolder rsqlVisitorFactoryHolder() {
- return RsqlVisitorFactoryHolder.getInstance();
+ RsqlConfigHolder rsqlVisitorFactoryHolder() {
+ return RsqlConfigHolder.getInstance();
}
/**
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitor.java
index 5222150d6..9efa097d1 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitor.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/JpaQueryRsqlVisitor.java
@@ -52,7 +52,7 @@ import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeMismatchException;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
+import org.springframework.util.ObjectUtils;
/**
* An implementation of the {@link RSQLVisitor} to visit the parsed tokens and
@@ -75,6 +75,7 @@ public class JpaQueryRsqlVisitor & FieldNameProvider, T> exten
private final CriteriaBuilder cb;
private final CriteriaQuery> query;
private final Database database;
+ private final boolean ensureIgnoreCase;
private final Root root;
private final SimpleTypeConverter simpleTypeConverter;
private final VirtualPropertyReplacer virtualPropertyReplacer;
@@ -85,7 +86,7 @@ public class JpaQueryRsqlVisitor & FieldNameProvider, T> exten
public JpaQueryRsqlVisitor(final Root root, final CriteriaBuilder cb, final Class enumType,
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database,
- final CriteriaQuery> query) {
+ final CriteriaQuery> query, final boolean ensureIgnoreCase) {
super(enumType);
this.root = root;
this.cb = cb;
@@ -93,7 +94,7 @@ public class JpaQueryRsqlVisitor & FieldNameProvider, T> exten
this.virtualPropertyReplacer = virtualPropertyReplacer;
this.simpleTypeConverter = new SimpleTypeConverter();
this.database = database;
- this.joinsNeeded = false;
+ this.ensureIgnoreCase = ensureIgnoreCase;
}
private void beginLevel(final boolean isOr) {
@@ -128,10 +129,10 @@ public class JpaQueryRsqlVisitor & FieldNameProvider, T> exten
@Override
public List visit(final AndNode node, final String param) {
beginLevel(false);
- final List childs = acceptChilds(node);
+ final List childs = acceptChildren(node);
endLevel();
if (!childs.isEmpty()) {
- return toSingleList(cb.and(childs.toArray(new Predicate[childs.size()])));
+ return toSingleList(cb.and(childs.toArray(new Predicate[0])));
}
return toSingleList(cb.conjunction());
}
@@ -139,10 +140,10 @@ public class JpaQueryRsqlVisitor & FieldNameProvider, T> exten
@Override
public List visit(final OrNode node, final String param) {
beginLevel(true);
- final List childs = acceptChilds(node);
+ final List childs = acceptChildren(node);
endLevel();
if (!childs.isEmpty()) {
- return toSingleList(cb.or(childs.toArray(new Predicate[childs.size()])));
+ return toSingleList(cb.or(childs.toArray(new Predicate[0])));
}
return toSingleList(cb.conjunction());
}
@@ -177,18 +178,17 @@ public class JpaQueryRsqlVisitor & FieldNameProvider, T> exten
() -> new RSQLParameterUnsupportedFieldException("RSQL field path cannot be empty", null));
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({"rawtypes", "unchecked"})
private Path> getJoinFieldPath(final Path> fieldPath, final String fieldNameSplit) {
- if (fieldPath instanceof PluralJoin) {
- final Join