You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2016/12/22 08:28:07 UTC
[1/2] syncope git commit: [SYNCOPE-983] Improving search performance
by skipping unnecessary checks for mandatory schemas
Repository: syncope
Updated Branches:
refs/heads/2_0_X 5a6173bb7 -> 8b5285e18
refs/heads/master 18ac4512c -> 941dc06a3
[SYNCOPE-983] Improving search performance by skipping unnecessary checks for mandatory schemas
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/8b5285e1
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/8b5285e1
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/8b5285e1
Branch: refs/heads/2_0_X
Commit: 8b5285e1863a21b64172d24ce4ffa804545f3541
Parents: 5a6173b
Author: Francesco Chicchiricc� <il...@apache.org>
Authored: Thu Dec 22 09:27:41 2016 +0100
Committer: Francesco Chicchiricc� <il...@apache.org>
Committed: Thu Dec 22 09:27:41 2016 +0100
----------------------------------------------------------------------
.../core/persistence/api/dao/AnySearchDAO.java | 3 +-
.../persistence/jpa/dao/JPAAnySearchDAO.java | 170 ++++++++++---------
.../core/persistence/jpa/dao/JPAGroupDAO.java | 6 +-
.../core/persistence/jpa/dao/JPARoleDAO.java | 4 +-
.../persistence/jpa/dao/OrderBySupport.java | 2 +
.../core/persistence/jpa/dao/SearchSupport.java | 8 +-
.../persistence/jpa/inner/AnySearchTest.java | 42 ++++-
.../notification/NotificationManagerImpl.java | 7 +-
.../apache/syncope/fit/core/RealmITCase.java | 2 +-
.../apache/syncope/fit/core/SearchITCase.java | 11 ++
10 files changed, 150 insertions(+), 105 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/8b5285e1/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
index b93ca49..fe5b572 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
@@ -79,9 +79,8 @@ public interface AnySearchDAO extends DAO<Any<?>> {
*
* @param any to be checked
* @param searchCondition to be verified
- * @param kind any object
* @param <T> any
* @return true if any matches searchCondition
*/
- <T extends Any<?>> boolean matches(T any, SearchCond searchCondition, AnyTypeKind kind);
+ <T extends Any<?>> boolean matches(T any, SearchCond searchCondition);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/8b5285e1/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index 9554f9a..49bf4ff 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -114,7 +114,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
}
}
- StringBuilder adminRealmFilter = new StringBuilder().
+ StringBuilder adminRealmFilter = new StringBuilder("u.any_id IN (").
append("SELECT any_id FROM ").append(svs.field().name).
append(" WHERE realm_id IN (SELECT id AS realm_id FROM Realm");
@@ -129,7 +129,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
adminRealmFilter.append(" id=?").append(setParameter(parameters, realmKey));
}
- adminRealmFilter.append(')');
+ adminRealmFilter.append("))");
return adminRealmFilter.toString();
}
@@ -144,8 +144,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
// 2. take into account administrative realms
queryString.insert(0, "SELECT u.any_id FROM (");
- queryString.append(") u WHERE any_id IN (");
- queryString.append(getAdminRealmsFilter(adminRealms, svs, parameters)).append(')');
+ queryString.append(") u WHERE ").append(getAdminRealmsFilter(adminRealms, svs, parameters));
// 3. prepare the COUNT query
queryString.insert(0, "SELECT COUNT(any_id) FROM (");
@@ -202,13 +201,11 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
}
@Override
- public <T extends Any<?>> boolean matches(
- final T any, final SearchCond cond, final AnyTypeKind typeKind) {
-
+ public <T extends Any<?>> boolean matches(final T any, final SearchCond cond) {
List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
// 1. get the query string from the search condition
- SearchSupport svs = new SearchSupport(typeKind);
+ SearchSupport svs = new SearchSupport(any.getType().getKind());
StringBuilder queryString = getQuery(cond, parameters, svs);
boolean matches;
@@ -257,52 +254,55 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
}
}
- private StringBuilder buildSelect(final OrderBySupport orderBySupport) {
+ private StringBuilder buildSelect(final OrderBySupport obs) {
final StringBuilder select = new StringBuilder("SELECT u.any_id");
- for (OrderBySupport.Item obs : orderBySupport.items) {
- select.append(',').append(obs.select);
+ for (OrderBySupport.Item item : obs.items) {
+ select.append(',').append(item.select);
}
select.append(" FROM ");
return select;
}
- private StringBuilder buildWhere(final OrderBySupport orderBySupport, final AnyTypeKind typeKind) {
- SearchSupport svs = new SearchSupport(typeKind);
+ private StringBuilder buildWhere(final SearchSupport svs, final OrderBySupport obs) {
StringBuilder where = new StringBuilder(" u");
- for (SearchSupport.SearchView searchView : orderBySupport.views) {
+ for (SearchSupport.SearchView searchView : obs.views) {
where.append(',');
if (searchView.name.equals(svs.attr().name)) {
- where.append(" (SELECT * FROM ").append(searchView.name).append(" UNION ").
- append("SELECT * FROM ").append(svs.nullAttr().name).append(')');
+ where.append(" (SELECT * FROM ").append(searchView.name);
+
+ if (svs.nonMandatorySchemas || obs.nonMandatorySchemas) {
+ where.append(" UNION SELECT * FROM ").append(svs.nullAttr().name);
+ }
+
+ where.append(')');
} else {
where.append(searchView.name);
}
where.append(' ').append(searchView.alias);
}
where.append(" WHERE ");
- for (SearchSupport.SearchView searchView : orderBySupport.views) {
+ for (SearchSupport.SearchView searchView : obs.views) {
where.append("u.any_id=").append(searchView.alias).append(".any_id AND ");
}
- for (OrderBySupport.Item obs : orderBySupport.items) {
- if (StringUtils.isNotBlank(obs.where)) {
- where.append(obs.where).append(" AND ");
+ for (OrderBySupport.Item item : obs.items) {
+ if (StringUtils.isNotBlank(item.where)) {
+ where.append(item.where).append(" AND ");
}
}
- where.append("u.any_id IN (");
return where;
}
- private StringBuilder buildOrderBy(final OrderBySupport orderBySupport) {
+ private StringBuilder buildOrderBy(final OrderBySupport obs) {
StringBuilder orderBy = new StringBuilder();
- for (OrderBySupport.Item obs : orderBySupport.items) {
- orderBy.append(obs.orderBy).append(',');
+ for (OrderBySupport.Item item : obs.items) {
+ orderBy.append(item.orderBy).append(',');
}
- if (!orderBySupport.items.isEmpty()) {
+ if (!obs.items.isEmpty()) {
orderBy.insert(0, " ORDER BY ");
orderBy.deleteCharAt(orderBy.length() - 1);
}
@@ -315,10 +315,10 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
final AnyUtils attrUtils = anyUtilsFactory.getInstance(type);
- OrderBySupport orderBySupport = new OrderBySupport();
+ OrderBySupport obs = new OrderBySupport();
for (OrderByClause clause : orderByClauses) {
- OrderBySupport.Item obs = new OrderBySupport.Item();
+ OrderBySupport.Item item = new OrderBySupport.Item();
// Manage difference among external key attribute and internal JPA @Id
String fieldName = "key".equals(clause.getField()) ? "id" : clause.getField();
@@ -327,44 +327,47 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
if (anyField == null) {
PlainSchema schema = schemaDAO.find(fieldName);
if (schema != null) {
+ // keep track of involvement of non-mandatory schemas in the order by clauses
+ obs.nonMandatorySchemas = !"true".equals(schema.getMandatoryCondition());
+
if (schema.isUniqueConstraint()) {
- orderBySupport.views.add(svs.uniqueAttr());
+ obs.views.add(svs.uniqueAttr());
- obs.select = new StringBuilder().
+ item.select = new StringBuilder().
append(svs.uniqueAttr().alias).append('.').append(svs.fieldName(schema.getType())).
append(" AS ").append(fieldName).toString();
- obs.where = new StringBuilder().
+ item.where = new StringBuilder().
append(svs.uniqueAttr().alias).
append(".schema_id='").append(fieldName).append("'").toString();
- obs.orderBy = fieldName + " " + clause.getDirection().name();
+ item.orderBy = fieldName + " " + clause.getDirection().name();
} else {
- orderBySupport.views.add(svs.attr());
+ obs.views.add(svs.attr());
- obs.select = new StringBuilder().
+ item.select = new StringBuilder().
append(svs.attr().alias).append('.').append(svs.fieldName(schema.getType())).
append(" AS ").append(fieldName).toString();
- obs.where = new StringBuilder().
+ item.where = new StringBuilder().
append(svs.attr().alias).
append(".schema_id='").append(fieldName).append("'").toString();
- obs.orderBy = fieldName + " " + clause.getDirection().name();
+ item.orderBy = fieldName + " " + clause.getDirection().name();
}
}
} else {
- orderBySupport.views.add(svs.field());
+ obs.views.add(svs.field());
- obs.select = svs.field().alias + "." + fieldName;
- obs.where = StringUtils.EMPTY;
- obs.orderBy = svs.field().alias + "." + fieldName + " " + clause.getDirection().name();
+ item.select = svs.field().alias + "." + fieldName;
+ item.where = StringUtils.EMPTY;
+ item.orderBy = svs.field().alias + "." + fieldName + " " + clause.getDirection().name();
}
- if (obs.isEmpty()) {
+ if (item.isEmpty()) {
LOG.warn("Cannot build any valid clause from {}", clause);
} else {
- orderBySupport.items.add(obs);
+ obs.items.add(item);
}
}
- return orderBySupport;
+ return obs;
}
@SuppressWarnings("unchecked")
@@ -379,17 +382,17 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
StringBuilder queryString = getQuery(cond, parameters, svs);
// 2. take into account administrative groups and ordering
- OrderBySupport orderBySupport = parseOrderBy(typeKind, svs, orderBy);
+ OrderBySupport obs = parseOrderBy(typeKind, svs, orderBy);
if (queryString.charAt(0) == '(') {
- queryString.insert(0, buildSelect(orderBySupport));
- queryString.append(buildWhere(orderBySupport, typeKind));
+ queryString.insert(0, buildSelect(obs));
+ queryString.append(buildWhere(svs, obs));
} else {
- queryString.insert(0, buildSelect(orderBySupport).append('('));
- queryString.append(')').append(buildWhere(orderBySupport, typeKind));
+ queryString.insert(0, buildSelect(obs).append('('));
+ queryString.append(')').append(buildWhere(svs, obs));
}
queryString.
- append(getAdminRealmsFilter(adminRealms, svs, parameters)).append(')').
- append(buildOrderBy(orderBySupport));
+ append(getAdminRealmsFilter(adminRealms, svs, parameters)).
+ append(buildOrderBy(obs));
// 3. prepare the search query
Query query = entityManager().createNativeQuery(queryString.toString());
@@ -434,30 +437,30 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
switch (cond.getType()) {
case LEAF:
case NOT_LEAF:
- if (cond.getAnyTypeCond() != null && AnyTypeKind.ANY_OBJECT == svs.anyTypeKind()) {
+ if (cond.getAnyTypeCond() != null && AnyTypeKind.ANY_OBJECT == svs.anyTypeKind) {
query.append(getQuery(cond.getAnyTypeCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
} else if (cond.getRelationshipTypeCond() != null
- && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) {
+ && (AnyTypeKind.USER == svs.anyTypeKind || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind)) {
query.append(getQuery(cond.getRelationshipTypeCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
} else if (cond.getRelationshipCond() != null
- && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) {
+ && (AnyTypeKind.USER == svs.anyTypeKind || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind)) {
query.append(getQuery(cond.getRelationshipCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
} else if (cond.getMembershipCond() != null
- && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) {
+ && (AnyTypeKind.USER == svs.anyTypeKind || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind)) {
query.append(getQuery(cond.getMembershipCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
} else if (cond.getAssignableCond() != null) {
query.append(getQuery(cond.getAssignableCond(), parameters, svs));
- } else if (cond.getRoleCond() != null && AnyTypeKind.USER == svs.anyTypeKind()) {
+ } else if (cond.getRoleCond() != null && AnyTypeKind.USER == svs.anyTypeKind) {
query.append(getQuery(cond.getRoleCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
- } else if (cond.getMemberCond() != null && AnyTypeKind.GROUP == svs.anyTypeKind()) {
+ } else if (cond.getMemberCond() != null && AnyTypeKind.GROUP == svs.anyTypeKind) {
query.append(getQuery(cond.getMemberCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
} else if (cond.getResourceCond() != null) {
@@ -498,8 +501,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query;
}
- private String getQuery(final AnyTypeCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final AnyTypeCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
append(svs.field().name).append(" WHERE type_id");
@@ -515,7 +518,10 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final RelationshipTypeCond cond, final boolean not, final List<Object> parameters,
+ private String getQuery(
+ final RelationshipTypeCond cond,
+ final boolean not,
+ final List<Object> parameters,
final SearchSupport svs) {
StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
@@ -538,8 +544,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final RelationshipCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final RelationshipCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
String rightAnyObjectKey;
if (SyncopeConstants.UUID_PATTERN.matcher(cond.getAnyObject()).matches()) {
@@ -569,8 +575,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final MembershipCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final MembershipCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
String groupKey;
if (SyncopeConstants.UUID_PATTERN.matcher(cond.getGroup()).matches()) {
@@ -611,8 +617,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final RoleCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final RoleCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
append(svs.field().name).append(" WHERE (");
@@ -642,8 +648,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final ResourceCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final ResourceCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
append(svs.field().name).append(" WHERE ");
@@ -659,7 +665,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
append(" WHERE resource_id=?").
append(setParameter(parameters, cond.getResourceKey()));
- if (svs.anyTypeKind() == AnyTypeKind.USER) {
+ if (svs.anyTypeKind == AnyTypeKind.USER) {
query.append(" UNION SELECT DISTINCT any_id FROM ").
append(svs.groupResource().name).
append(" WHERE resource_id=?").
@@ -695,8 +701,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final MemberCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final MemberCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
String memberKey;
if (SyncopeConstants.UUID_PATTERN.matcher(cond.getMember()).matches()) {
@@ -740,9 +746,14 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private void fillAttributeQuery(final StringBuilder query, final PlainAttrValue attrValue,
- final PlainSchema schema, final AttributeCond cond, final boolean not,
- final List<Object> parameters, final SearchSupport svs) {
+ private void fillAttributeQuery(
+ final StringBuilder query,
+ final PlainAttrValue attrValue,
+ final PlainSchema schema,
+ final AttributeCond cond,
+ final boolean not,
+ final List<Object> parameters,
+ final SearchSupport svs) {
// activate ignoreCase only for EQ and LIKE operators
boolean ignoreCase = AttributeCond.Type.ILIKE == cond.getType() || AttributeCond.Type.IEQ == cond.getType();
@@ -850,10 +861,10 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
}
}
- private String getQuery(final AttributeCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final AttributeCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
- AnyUtils attrUtils = anyUtilsFactory.getInstance(svs.anyTypeKind());
+ AnyUtils attrUtils = anyUtilsFactory.getInstance(svs.anyTypeKind);
PlainSchema schema = schemaDAO.find(cond.getSchema());
if (schema == null) {
@@ -861,6 +872,9 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return EMPTY_QUERY;
}
+ // keep track of involvement of non-mandatory schemas in the search condition
+ svs.nonMandatorySchemas = !"true".equals(schema.getMandatoryCondition());
+
PlainAttrValue attrValue = attrUtils.newPlainAttrValue();
try {
if (cond.getType() != AttributeCond.Type.LIKE
@@ -902,12 +916,12 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final AnyCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final AnyCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
AnyCond condClone = SerializationUtils.clone(cond);
- AnyUtils attrUtils = anyUtilsFactory.getInstance(svs.anyTypeKind());
+ AnyUtils attrUtils = anyUtilsFactory.getInstance(svs.anyTypeKind);
// Keeps track of difference between entity's getKey() and JPA @Id fields
if ("key".equals(condClone.getSchema())) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/8b5285e1/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
index 1785672..0bcdee2 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
@@ -290,8 +290,7 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
for (ADynGroupMembership memb : group.getADynMemberships()) {
if (searchDAO.matches(
anyObject,
- buildDynMembershipCond(memb.getFIQLCond(), group.getRealm()),
- AnyTypeKind.ANY_OBJECT)) {
+ buildDynMembershipCond(memb.getFIQLCond(), group.getRealm()))) {
memb.add(anyObject);
} else {
@@ -308,8 +307,7 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
if (group.getUDynMembership() != null) {
if (searchDAO.matches(
user,
- buildDynMembershipCond(group.getUDynMembership().getFIQLCond(), group.getRealm()),
- AnyTypeKind.USER)) {
+ buildDynMembershipCond(group.getUDynMembership().getFIQLCond(), group.getRealm()))) {
group.getUDynMembership().add(user);
} else {
http://git-wip-us.apache.org/repos/asf/syncope/blob/8b5285e1/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
index fc91712..b636fc6 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
@@ -111,9 +111,7 @@ public class JPARoleDAO extends AbstractDAO<Role> implements RoleDAO {
public void refreshDynMemberships(final User user) {
for (Role role : findAll()) {
if (role.getDynMembership() != null) {
- if (searchDAO.matches(user,
- SearchCondConverter.convert(role.getDynMembership().getFIQLCond()), AnyTypeKind.USER)) {
-
+ if (searchDAO.matches(user, SearchCondConverter.convert(role.getDynMembership().getFIQLCond()))) {
role.getDynMembership().add(user);
} else {
role.getDynMembership().getMembers().remove(user);
http://git-wip-us.apache.org/repos/asf/syncope/blob/8b5285e1/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OrderBySupport.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OrderBySupport.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OrderBySupport.java
index 63f442e..ec87f5b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OrderBySupport.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OrderBySupport.java
@@ -44,4 +44,6 @@ class OrderBySupport {
protected List<Item> items = new ArrayList<>();
+ protected boolean nonMandatorySchemas = false;
+
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/8b5285e1/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
index 06854df..9964d89 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
@@ -47,16 +47,14 @@ class SearchSupport {
}
}
- private final AnyTypeKind anyTypeKind;
+ protected final AnyTypeKind anyTypeKind;
+
+ protected boolean nonMandatorySchemas = false;
SearchSupport(final AnyTypeKind anyTypeKind) {
this.anyTypeKind = anyTypeKind;
}
- public AnyTypeKind anyTypeKind() {
- return anyTypeKind;
- }
-
public String fieldName(final AttrSchemaType attrSchemaType) {
String result;
http://git-wip-us.apache.org/repos/asf/syncope/blob/8b5285e1/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
index 429dfb5..c7e5c62 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
@@ -89,11 +89,11 @@ public class AnySearchTest extends AbstractTest {
RelationshipCond relationshipCond = new RelationshipCond();
relationshipCond.setAnyObject("Canon MF 8030cn");
- assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(relationshipCond), AnyTypeKind.ANY_OBJECT));
+ assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(relationshipCond)));
RelationshipTypeCond relationshipTypeCond = new RelationshipTypeCond();
relationshipTypeCond.setRelationshipTypeKey("neighborhood");
- assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(relationshipTypeCond), AnyTypeKind.ANY_OBJECT));
+ assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(relationshipTypeCond)));
}
@Test
@@ -103,25 +103,25 @@ public class AnySearchTest extends AbstractTest {
MembershipCond groupCond = new MembershipCond();
groupCond.setGroup("secretary");
- assertFalse(searchDAO.matches(user, SearchCond.getLeafCond(groupCond), AnyTypeKind.USER));
+ assertFalse(searchDAO.matches(user, SearchCond.getLeafCond(groupCond)));
groupCond.setGroup("root");
- assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(groupCond), AnyTypeKind.USER));
+ assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(groupCond)));
RoleCond roleCond = new RoleCond();
roleCond.setRoleKey("Other");
- assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(roleCond), AnyTypeKind.USER));
+ assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(roleCond)));
user = userDAO.find("c9b2dec2-00a7-4855-97c0-d854842b4b24");
assertNotNull(user);
RelationshipCond relationshipCond = new RelationshipCond();
relationshipCond.setAnyObject("fc6dbc3a-6c07-4965-8781-921e7401a4a5");
- assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(relationshipCond), AnyTypeKind.USER));
+ assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(relationshipCond)));
RelationshipTypeCond relationshipTypeCond = new RelationshipTypeCond();
relationshipTypeCond.setRelationshipTypeKey("neighborhood");
- assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(relationshipTypeCond), AnyTypeKind.USER));
+ assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(relationshipTypeCond)));
}
@Test
@@ -133,7 +133,7 @@ public class AnySearchTest extends AbstractTest {
attrCond.setSchema("show");
attrCond.setType(AttributeCond.Type.ISNOTNULL);
- assertTrue(searchDAO.matches(group, SearchCond.getLeafCond(attrCond), AnyTypeKind.GROUP));
+ assertTrue(searchDAO.matches(group, SearchCond.getLeafCond(attrCond)));
}
@Test
@@ -755,4 +755,30 @@ public class AnySearchTest extends AbstractTest {
matching = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
assertEquals(1, matching.size());
}
+
+ @Test
+ public void issueSYNCOPE983() {
+ AttributeCond fullnameLeafCond = new AttributeCond(AttributeCond.Type.LIKE);
+ fullnameLeafCond.setSchema("surname");
+ fullnameLeafCond.setExpression("%o%");
+
+ List<OrderByClause> orderByClauses = new ArrayList<>();
+ OrderByClause orderByClause = new OrderByClause();
+ orderByClause.setField("surname");
+ orderByClause.setDirection(OrderByClause.Direction.ASC);
+ orderByClauses.add(orderByClause);
+ orderByClause = new OrderByClause();
+ orderByClause.setField("username");
+ orderByClause.setDirection(OrderByClause.Direction.DESC);
+ orderByClauses.add(orderByClause);
+
+ List<User> users = searchDAO.search(
+ SyncopeConstants.FULL_ADMIN_REALMS,
+ SearchCond.getLeafCond(fullnameLeafCond),
+ -1,
+ -1,
+ orderByClauses,
+ AnyTypeKind.USER);
+ assertFalse(users.isEmpty());
+ }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/8b5285e1/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
index e5982c4..6248185 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
@@ -212,8 +212,8 @@ public class NotificationManagerImpl implements NotificationManager {
try {
NotificationRecipientsProvider recipientsProvider =
(NotificationRecipientsProvider) ApplicationContextProvider.getBeanFactory().
- createBean(Class.forName(notification.getRecipientsProviderClassName()),
- AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+ createBean(Class.forName(notification.getRecipientsProviderClassName()),
+ AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
recipientEmails.addAll(recipientsProvider.provideRecipients(notification));
} catch (Exception e) {
LOG.error("Could not fetch recipients from {}", notification.getRecipientsProviderClassName(), e);
@@ -309,8 +309,7 @@ public class NotificationManagerImpl implements NotificationManager {
LOG.debug("No events found about {}", any);
} else if (anyType == null || any == null
|| notification.getAbout(anyType) == null
- || searchDAO.matches(any,
- SearchCondConverter.convert(notification.getAbout(anyType).get()), anyType.getKind())) {
+ || searchDAO.matches(any, SearchCondConverter.convert(notification.getAbout(anyType).get()))) {
LOG.debug("Creating notification task for event {} about {}", currentEvent, any);
http://git-wip-us.apache.org/repos/asf/syncope/blob/8b5285e1/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
index 3d1622e..ae2bf7b 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
@@ -168,7 +168,7 @@ public class RealmITCase extends AbstractITCase {
@Test
public void delete() {
RealmTO realm = new RealmTO();
- realm.setName("deletable");
+ realm.setName("deletable3");
Response response = realmService.create("/even/two", realm);
RealmTO[] actuals = getObject(response.getLocation(), RealmService.class, RealmTO[].class);
http://git-wip-us.apache.org/repos/asf/syncope/blob/8b5285e1/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
index c652cde..976c11c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
@@ -20,6 +20,7 @@ package org.apache.syncope.fit.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -521,4 +522,14 @@ public class SearchITCase extends AbstractITCase {
anyTypeService.delete(service.getKey());
}
}
+
+ @Test
+ public void issueSYNCOPE983() {
+ PagedResult<UserTO> users = userService.search(
+ new AnyQuery.Builder().
+ fiql(SyncopeClient.getUserSearchConditionBuilder().is("surname").equalTo("*o*").query()).
+ orderBy(SyncopeClient.getOrderByClauseBuilder().asc("surname").desc("username").build()).
+ build());
+ assertNotEquals(0, users.getTotalCount());
+ }
}
[2/2] syncope git commit: [SYNCOPE-983] Improving search performance
by skipping unnecessary checks for mandatory schemas
Posted by il...@apache.org.
[SYNCOPE-983] Improving search performance by skipping unnecessary checks for mandatory schemas
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/941dc06a
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/941dc06a
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/941dc06a
Branch: refs/heads/master
Commit: 941dc06a30e14122bd4552de0c600d273a6592b5
Parents: 18ac451
Author: Francesco Chicchiricc� <il...@apache.org>
Authored: Thu Dec 22 09:27:41 2016 +0100
Committer: Francesco Chicchiricc� <il...@apache.org>
Committed: Thu Dec 22 09:27:51 2016 +0100
----------------------------------------------------------------------
.../core/persistence/api/dao/AnySearchDAO.java | 3 +-
.../persistence/jpa/dao/JPAAnySearchDAO.java | 170 ++++++++++---------
.../core/persistence/jpa/dao/JPAGroupDAO.java | 6 +-
.../core/persistence/jpa/dao/JPARoleDAO.java | 4 +-
.../persistence/jpa/dao/OrderBySupport.java | 2 +
.../core/persistence/jpa/dao/SearchSupport.java | 8 +-
.../persistence/jpa/inner/AnySearchTest.java | 42 ++++-
.../notification/NotificationManagerImpl.java | 7 +-
.../apache/syncope/fit/core/RealmITCase.java | 2 +-
.../apache/syncope/fit/core/SearchITCase.java | 11 ++
10 files changed, 150 insertions(+), 105 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/941dc06a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
index b93ca49..fe5b572 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
@@ -79,9 +79,8 @@ public interface AnySearchDAO extends DAO<Any<?>> {
*
* @param any to be checked
* @param searchCondition to be verified
- * @param kind any object
* @param <T> any
* @return true if any matches searchCondition
*/
- <T extends Any<?>> boolean matches(T any, SearchCond searchCondition, AnyTypeKind kind);
+ <T extends Any<?>> boolean matches(T any, SearchCond searchCondition);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/941dc06a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index 9554f9a..49bf4ff 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -114,7 +114,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
}
}
- StringBuilder adminRealmFilter = new StringBuilder().
+ StringBuilder adminRealmFilter = new StringBuilder("u.any_id IN (").
append("SELECT any_id FROM ").append(svs.field().name).
append(" WHERE realm_id IN (SELECT id AS realm_id FROM Realm");
@@ -129,7 +129,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
adminRealmFilter.append(" id=?").append(setParameter(parameters, realmKey));
}
- adminRealmFilter.append(')');
+ adminRealmFilter.append("))");
return adminRealmFilter.toString();
}
@@ -144,8 +144,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
// 2. take into account administrative realms
queryString.insert(0, "SELECT u.any_id FROM (");
- queryString.append(") u WHERE any_id IN (");
- queryString.append(getAdminRealmsFilter(adminRealms, svs, parameters)).append(')');
+ queryString.append(") u WHERE ").append(getAdminRealmsFilter(adminRealms, svs, parameters));
// 3. prepare the COUNT query
queryString.insert(0, "SELECT COUNT(any_id) FROM (");
@@ -202,13 +201,11 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
}
@Override
- public <T extends Any<?>> boolean matches(
- final T any, final SearchCond cond, final AnyTypeKind typeKind) {
-
+ public <T extends Any<?>> boolean matches(final T any, final SearchCond cond) {
List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
// 1. get the query string from the search condition
- SearchSupport svs = new SearchSupport(typeKind);
+ SearchSupport svs = new SearchSupport(any.getType().getKind());
StringBuilder queryString = getQuery(cond, parameters, svs);
boolean matches;
@@ -257,52 +254,55 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
}
}
- private StringBuilder buildSelect(final OrderBySupport orderBySupport) {
+ private StringBuilder buildSelect(final OrderBySupport obs) {
final StringBuilder select = new StringBuilder("SELECT u.any_id");
- for (OrderBySupport.Item obs : orderBySupport.items) {
- select.append(',').append(obs.select);
+ for (OrderBySupport.Item item : obs.items) {
+ select.append(',').append(item.select);
}
select.append(" FROM ");
return select;
}
- private StringBuilder buildWhere(final OrderBySupport orderBySupport, final AnyTypeKind typeKind) {
- SearchSupport svs = new SearchSupport(typeKind);
+ private StringBuilder buildWhere(final SearchSupport svs, final OrderBySupport obs) {
StringBuilder where = new StringBuilder(" u");
- for (SearchSupport.SearchView searchView : orderBySupport.views) {
+ for (SearchSupport.SearchView searchView : obs.views) {
where.append(',');
if (searchView.name.equals(svs.attr().name)) {
- where.append(" (SELECT * FROM ").append(searchView.name).append(" UNION ").
- append("SELECT * FROM ").append(svs.nullAttr().name).append(')');
+ where.append(" (SELECT * FROM ").append(searchView.name);
+
+ if (svs.nonMandatorySchemas || obs.nonMandatorySchemas) {
+ where.append(" UNION SELECT * FROM ").append(svs.nullAttr().name);
+ }
+
+ where.append(')');
} else {
where.append(searchView.name);
}
where.append(' ').append(searchView.alias);
}
where.append(" WHERE ");
- for (SearchSupport.SearchView searchView : orderBySupport.views) {
+ for (SearchSupport.SearchView searchView : obs.views) {
where.append("u.any_id=").append(searchView.alias).append(".any_id AND ");
}
- for (OrderBySupport.Item obs : orderBySupport.items) {
- if (StringUtils.isNotBlank(obs.where)) {
- where.append(obs.where).append(" AND ");
+ for (OrderBySupport.Item item : obs.items) {
+ if (StringUtils.isNotBlank(item.where)) {
+ where.append(item.where).append(" AND ");
}
}
- where.append("u.any_id IN (");
return where;
}
- private StringBuilder buildOrderBy(final OrderBySupport orderBySupport) {
+ private StringBuilder buildOrderBy(final OrderBySupport obs) {
StringBuilder orderBy = new StringBuilder();
- for (OrderBySupport.Item obs : orderBySupport.items) {
- orderBy.append(obs.orderBy).append(',');
+ for (OrderBySupport.Item item : obs.items) {
+ orderBy.append(item.orderBy).append(',');
}
- if (!orderBySupport.items.isEmpty()) {
+ if (!obs.items.isEmpty()) {
orderBy.insert(0, " ORDER BY ");
orderBy.deleteCharAt(orderBy.length() - 1);
}
@@ -315,10 +315,10 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
final AnyUtils attrUtils = anyUtilsFactory.getInstance(type);
- OrderBySupport orderBySupport = new OrderBySupport();
+ OrderBySupport obs = new OrderBySupport();
for (OrderByClause clause : orderByClauses) {
- OrderBySupport.Item obs = new OrderBySupport.Item();
+ OrderBySupport.Item item = new OrderBySupport.Item();
// Manage difference among external key attribute and internal JPA @Id
String fieldName = "key".equals(clause.getField()) ? "id" : clause.getField();
@@ -327,44 +327,47 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
if (anyField == null) {
PlainSchema schema = schemaDAO.find(fieldName);
if (schema != null) {
+ // keep track of involvement of non-mandatory schemas in the order by clauses
+ obs.nonMandatorySchemas = !"true".equals(schema.getMandatoryCondition());
+
if (schema.isUniqueConstraint()) {
- orderBySupport.views.add(svs.uniqueAttr());
+ obs.views.add(svs.uniqueAttr());
- obs.select = new StringBuilder().
+ item.select = new StringBuilder().
append(svs.uniqueAttr().alias).append('.').append(svs.fieldName(schema.getType())).
append(" AS ").append(fieldName).toString();
- obs.where = new StringBuilder().
+ item.where = new StringBuilder().
append(svs.uniqueAttr().alias).
append(".schema_id='").append(fieldName).append("'").toString();
- obs.orderBy = fieldName + " " + clause.getDirection().name();
+ item.orderBy = fieldName + " " + clause.getDirection().name();
} else {
- orderBySupport.views.add(svs.attr());
+ obs.views.add(svs.attr());
- obs.select = new StringBuilder().
+ item.select = new StringBuilder().
append(svs.attr().alias).append('.').append(svs.fieldName(schema.getType())).
append(" AS ").append(fieldName).toString();
- obs.where = new StringBuilder().
+ item.where = new StringBuilder().
append(svs.attr().alias).
append(".schema_id='").append(fieldName).append("'").toString();
- obs.orderBy = fieldName + " " + clause.getDirection().name();
+ item.orderBy = fieldName + " " + clause.getDirection().name();
}
}
} else {
- orderBySupport.views.add(svs.field());
+ obs.views.add(svs.field());
- obs.select = svs.field().alias + "." + fieldName;
- obs.where = StringUtils.EMPTY;
- obs.orderBy = svs.field().alias + "." + fieldName + " " + clause.getDirection().name();
+ item.select = svs.field().alias + "." + fieldName;
+ item.where = StringUtils.EMPTY;
+ item.orderBy = svs.field().alias + "." + fieldName + " " + clause.getDirection().name();
}
- if (obs.isEmpty()) {
+ if (item.isEmpty()) {
LOG.warn("Cannot build any valid clause from {}", clause);
} else {
- orderBySupport.items.add(obs);
+ obs.items.add(item);
}
}
- return orderBySupport;
+ return obs;
}
@SuppressWarnings("unchecked")
@@ -379,17 +382,17 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
StringBuilder queryString = getQuery(cond, parameters, svs);
// 2. take into account administrative groups and ordering
- OrderBySupport orderBySupport = parseOrderBy(typeKind, svs, orderBy);
+ OrderBySupport obs = parseOrderBy(typeKind, svs, orderBy);
if (queryString.charAt(0) == '(') {
- queryString.insert(0, buildSelect(orderBySupport));
- queryString.append(buildWhere(orderBySupport, typeKind));
+ queryString.insert(0, buildSelect(obs));
+ queryString.append(buildWhere(svs, obs));
} else {
- queryString.insert(0, buildSelect(orderBySupport).append('('));
- queryString.append(')').append(buildWhere(orderBySupport, typeKind));
+ queryString.insert(0, buildSelect(obs).append('('));
+ queryString.append(')').append(buildWhere(svs, obs));
}
queryString.
- append(getAdminRealmsFilter(adminRealms, svs, parameters)).append(')').
- append(buildOrderBy(orderBySupport));
+ append(getAdminRealmsFilter(adminRealms, svs, parameters)).
+ append(buildOrderBy(obs));
// 3. prepare the search query
Query query = entityManager().createNativeQuery(queryString.toString());
@@ -434,30 +437,30 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
switch (cond.getType()) {
case LEAF:
case NOT_LEAF:
- if (cond.getAnyTypeCond() != null && AnyTypeKind.ANY_OBJECT == svs.anyTypeKind()) {
+ if (cond.getAnyTypeCond() != null && AnyTypeKind.ANY_OBJECT == svs.anyTypeKind) {
query.append(getQuery(cond.getAnyTypeCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
} else if (cond.getRelationshipTypeCond() != null
- && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) {
+ && (AnyTypeKind.USER == svs.anyTypeKind || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind)) {
query.append(getQuery(cond.getRelationshipTypeCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
} else if (cond.getRelationshipCond() != null
- && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) {
+ && (AnyTypeKind.USER == svs.anyTypeKind || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind)) {
query.append(getQuery(cond.getRelationshipCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
} else if (cond.getMembershipCond() != null
- && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) {
+ && (AnyTypeKind.USER == svs.anyTypeKind || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind)) {
query.append(getQuery(cond.getMembershipCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
} else if (cond.getAssignableCond() != null) {
query.append(getQuery(cond.getAssignableCond(), parameters, svs));
- } else if (cond.getRoleCond() != null && AnyTypeKind.USER == svs.anyTypeKind()) {
+ } else if (cond.getRoleCond() != null && AnyTypeKind.USER == svs.anyTypeKind) {
query.append(getQuery(cond.getRoleCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
- } else if (cond.getMemberCond() != null && AnyTypeKind.GROUP == svs.anyTypeKind()) {
+ } else if (cond.getMemberCond() != null && AnyTypeKind.GROUP == svs.anyTypeKind) {
query.append(getQuery(cond.getMemberCond(),
cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
} else if (cond.getResourceCond() != null) {
@@ -498,8 +501,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query;
}
- private String getQuery(final AnyTypeCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final AnyTypeCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
append(svs.field().name).append(" WHERE type_id");
@@ -515,7 +518,10 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final RelationshipTypeCond cond, final boolean not, final List<Object> parameters,
+ private String getQuery(
+ final RelationshipTypeCond cond,
+ final boolean not,
+ final List<Object> parameters,
final SearchSupport svs) {
StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
@@ -538,8 +544,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final RelationshipCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final RelationshipCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
String rightAnyObjectKey;
if (SyncopeConstants.UUID_PATTERN.matcher(cond.getAnyObject()).matches()) {
@@ -569,8 +575,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final MembershipCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final MembershipCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
String groupKey;
if (SyncopeConstants.UUID_PATTERN.matcher(cond.getGroup()).matches()) {
@@ -611,8 +617,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final RoleCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final RoleCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
append(svs.field().name).append(" WHERE (");
@@ -642,8 +648,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final ResourceCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final ResourceCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
append(svs.field().name).append(" WHERE ");
@@ -659,7 +665,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
append(" WHERE resource_id=?").
append(setParameter(parameters, cond.getResourceKey()));
- if (svs.anyTypeKind() == AnyTypeKind.USER) {
+ if (svs.anyTypeKind == AnyTypeKind.USER) {
query.append(" UNION SELECT DISTINCT any_id FROM ").
append(svs.groupResource().name).
append(" WHERE resource_id=?").
@@ -695,8 +701,8 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final MemberCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final MemberCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
String memberKey;
if (SyncopeConstants.UUID_PATTERN.matcher(cond.getMember()).matches()) {
@@ -740,9 +746,14 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private void fillAttributeQuery(final StringBuilder query, final PlainAttrValue attrValue,
- final PlainSchema schema, final AttributeCond cond, final boolean not,
- final List<Object> parameters, final SearchSupport svs) {
+ private void fillAttributeQuery(
+ final StringBuilder query,
+ final PlainAttrValue attrValue,
+ final PlainSchema schema,
+ final AttributeCond cond,
+ final boolean not,
+ final List<Object> parameters,
+ final SearchSupport svs) {
// activate ignoreCase only for EQ and LIKE operators
boolean ignoreCase = AttributeCond.Type.ILIKE == cond.getType() || AttributeCond.Type.IEQ == cond.getType();
@@ -850,10 +861,10 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
}
}
- private String getQuery(final AttributeCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final AttributeCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
- AnyUtils attrUtils = anyUtilsFactory.getInstance(svs.anyTypeKind());
+ AnyUtils attrUtils = anyUtilsFactory.getInstance(svs.anyTypeKind);
PlainSchema schema = schemaDAO.find(cond.getSchema());
if (schema == null) {
@@ -861,6 +872,9 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return EMPTY_QUERY;
}
+ // keep track of involvement of non-mandatory schemas in the search condition
+ svs.nonMandatorySchemas = !"true".equals(schema.getMandatoryCondition());
+
PlainAttrValue attrValue = attrUtils.newPlainAttrValue();
try {
if (cond.getType() != AttributeCond.Type.LIKE
@@ -902,12 +916,12 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
return query.toString();
}
- private String getQuery(final AnyCond cond, final boolean not, final List<Object> parameters,
- final SearchSupport svs) {
+ private String getQuery(
+ final AnyCond cond, final boolean not, final List<Object> parameters, final SearchSupport svs) {
AnyCond condClone = SerializationUtils.clone(cond);
- AnyUtils attrUtils = anyUtilsFactory.getInstance(svs.anyTypeKind());
+ AnyUtils attrUtils = anyUtilsFactory.getInstance(svs.anyTypeKind);
// Keeps track of difference between entity's getKey() and JPA @Id fields
if ("key".equals(condClone.getSchema())) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/941dc06a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
index 1785672..0bcdee2 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
@@ -290,8 +290,7 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
for (ADynGroupMembership memb : group.getADynMemberships()) {
if (searchDAO.matches(
anyObject,
- buildDynMembershipCond(memb.getFIQLCond(), group.getRealm()),
- AnyTypeKind.ANY_OBJECT)) {
+ buildDynMembershipCond(memb.getFIQLCond(), group.getRealm()))) {
memb.add(anyObject);
} else {
@@ -308,8 +307,7 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
if (group.getUDynMembership() != null) {
if (searchDAO.matches(
user,
- buildDynMembershipCond(group.getUDynMembership().getFIQLCond(), group.getRealm()),
- AnyTypeKind.USER)) {
+ buildDynMembershipCond(group.getUDynMembership().getFIQLCond(), group.getRealm()))) {
group.getUDynMembership().add(user);
} else {
http://git-wip-us.apache.org/repos/asf/syncope/blob/941dc06a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
index fc91712..b636fc6 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
@@ -111,9 +111,7 @@ public class JPARoleDAO extends AbstractDAO<Role> implements RoleDAO {
public void refreshDynMemberships(final User user) {
for (Role role : findAll()) {
if (role.getDynMembership() != null) {
- if (searchDAO.matches(user,
- SearchCondConverter.convert(role.getDynMembership().getFIQLCond()), AnyTypeKind.USER)) {
-
+ if (searchDAO.matches(user, SearchCondConverter.convert(role.getDynMembership().getFIQLCond()))) {
role.getDynMembership().add(user);
} else {
role.getDynMembership().getMembers().remove(user);
http://git-wip-us.apache.org/repos/asf/syncope/blob/941dc06a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OrderBySupport.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OrderBySupport.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OrderBySupport.java
index 63f442e..ec87f5b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OrderBySupport.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OrderBySupport.java
@@ -44,4 +44,6 @@ class OrderBySupport {
protected List<Item> items = new ArrayList<>();
+ protected boolean nonMandatorySchemas = false;
+
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/941dc06a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
index 06854df..9964d89 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
@@ -47,16 +47,14 @@ class SearchSupport {
}
}
- private final AnyTypeKind anyTypeKind;
+ protected final AnyTypeKind anyTypeKind;
+
+ protected boolean nonMandatorySchemas = false;
SearchSupport(final AnyTypeKind anyTypeKind) {
this.anyTypeKind = anyTypeKind;
}
- public AnyTypeKind anyTypeKind() {
- return anyTypeKind;
- }
-
public String fieldName(final AttrSchemaType attrSchemaType) {
String result;
http://git-wip-us.apache.org/repos/asf/syncope/blob/941dc06a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
index 429dfb5..c7e5c62 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
@@ -89,11 +89,11 @@ public class AnySearchTest extends AbstractTest {
RelationshipCond relationshipCond = new RelationshipCond();
relationshipCond.setAnyObject("Canon MF 8030cn");
- assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(relationshipCond), AnyTypeKind.ANY_OBJECT));
+ assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(relationshipCond)));
RelationshipTypeCond relationshipTypeCond = new RelationshipTypeCond();
relationshipTypeCond.setRelationshipTypeKey("neighborhood");
- assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(relationshipTypeCond), AnyTypeKind.ANY_OBJECT));
+ assertTrue(searchDAO.matches(anyObject, SearchCond.getLeafCond(relationshipTypeCond)));
}
@Test
@@ -103,25 +103,25 @@ public class AnySearchTest extends AbstractTest {
MembershipCond groupCond = new MembershipCond();
groupCond.setGroup("secretary");
- assertFalse(searchDAO.matches(user, SearchCond.getLeafCond(groupCond), AnyTypeKind.USER));
+ assertFalse(searchDAO.matches(user, SearchCond.getLeafCond(groupCond)));
groupCond.setGroup("root");
- assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(groupCond), AnyTypeKind.USER));
+ assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(groupCond)));
RoleCond roleCond = new RoleCond();
roleCond.setRoleKey("Other");
- assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(roleCond), AnyTypeKind.USER));
+ assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(roleCond)));
user = userDAO.find("c9b2dec2-00a7-4855-97c0-d854842b4b24");
assertNotNull(user);
RelationshipCond relationshipCond = new RelationshipCond();
relationshipCond.setAnyObject("fc6dbc3a-6c07-4965-8781-921e7401a4a5");
- assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(relationshipCond), AnyTypeKind.USER));
+ assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(relationshipCond)));
RelationshipTypeCond relationshipTypeCond = new RelationshipTypeCond();
relationshipTypeCond.setRelationshipTypeKey("neighborhood");
- assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(relationshipTypeCond), AnyTypeKind.USER));
+ assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(relationshipTypeCond)));
}
@Test
@@ -133,7 +133,7 @@ public class AnySearchTest extends AbstractTest {
attrCond.setSchema("show");
attrCond.setType(AttributeCond.Type.ISNOTNULL);
- assertTrue(searchDAO.matches(group, SearchCond.getLeafCond(attrCond), AnyTypeKind.GROUP));
+ assertTrue(searchDAO.matches(group, SearchCond.getLeafCond(attrCond)));
}
@Test
@@ -755,4 +755,30 @@ public class AnySearchTest extends AbstractTest {
matching = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
assertEquals(1, matching.size());
}
+
+ @Test
+ public void issueSYNCOPE983() {
+ AttributeCond fullnameLeafCond = new AttributeCond(AttributeCond.Type.LIKE);
+ fullnameLeafCond.setSchema("surname");
+ fullnameLeafCond.setExpression("%o%");
+
+ List<OrderByClause> orderByClauses = new ArrayList<>();
+ OrderByClause orderByClause = new OrderByClause();
+ orderByClause.setField("surname");
+ orderByClause.setDirection(OrderByClause.Direction.ASC);
+ orderByClauses.add(orderByClause);
+ orderByClause = new OrderByClause();
+ orderByClause.setField("username");
+ orderByClause.setDirection(OrderByClause.Direction.DESC);
+ orderByClauses.add(orderByClause);
+
+ List<User> users = searchDAO.search(
+ SyncopeConstants.FULL_ADMIN_REALMS,
+ SearchCond.getLeafCond(fullnameLeafCond),
+ -1,
+ -1,
+ orderByClauses,
+ AnyTypeKind.USER);
+ assertFalse(users.isEmpty());
+ }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/941dc06a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
index e5982c4..6248185 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
@@ -212,8 +212,8 @@ public class NotificationManagerImpl implements NotificationManager {
try {
NotificationRecipientsProvider recipientsProvider =
(NotificationRecipientsProvider) ApplicationContextProvider.getBeanFactory().
- createBean(Class.forName(notification.getRecipientsProviderClassName()),
- AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+ createBean(Class.forName(notification.getRecipientsProviderClassName()),
+ AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
recipientEmails.addAll(recipientsProvider.provideRecipients(notification));
} catch (Exception e) {
LOG.error("Could not fetch recipients from {}", notification.getRecipientsProviderClassName(), e);
@@ -309,8 +309,7 @@ public class NotificationManagerImpl implements NotificationManager {
LOG.debug("No events found about {}", any);
} else if (anyType == null || any == null
|| notification.getAbout(anyType) == null
- || searchDAO.matches(any,
- SearchCondConverter.convert(notification.getAbout(anyType).get()), anyType.getKind())) {
+ || searchDAO.matches(any, SearchCondConverter.convert(notification.getAbout(anyType).get()))) {
LOG.debug("Creating notification task for event {} about {}", currentEvent, any);
http://git-wip-us.apache.org/repos/asf/syncope/blob/941dc06a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
index 3d1622e..ae2bf7b 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
@@ -168,7 +168,7 @@ public class RealmITCase extends AbstractITCase {
@Test
public void delete() {
RealmTO realm = new RealmTO();
- realm.setName("deletable");
+ realm.setName("deletable3");
Response response = realmService.create("/even/two", realm);
RealmTO[] actuals = getObject(response.getLocation(), RealmService.class, RealmTO[].class);
http://git-wip-us.apache.org/repos/asf/syncope/blob/941dc06a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
index c652cde..976c11c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
@@ -20,6 +20,7 @@ package org.apache.syncope.fit.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -521,4 +522,14 @@ public class SearchITCase extends AbstractITCase {
anyTypeService.delete(service.getKey());
}
}
+
+ @Test
+ public void issueSYNCOPE983() {
+ PagedResult<UserTO> users = userService.search(
+ new AnyQuery.Builder().
+ fiql(SyncopeClient.getUserSearchConditionBuilder().is("surname").equalTo("*o*").query()).
+ orderBy(SyncopeClient.getOrderByClauseBuilder().asc("surname").desc("username").build()).
+ build());
+ assertNotEquals(0, users.getTotalCount());
+ }
}