From 3d1c794d63cd1cbce94ff577d4b4c352b9212bf9 Mon Sep 17 00:00:00 2001 From: vcrescia Date: Fri, 10 Jul 2026 15:36:29 +0200 Subject: [PATCH 1/4] [SYNCOPE-1982] Improve query perfomance on OraclePlainSchemaRepoExtImpl --- .../repo/OraclePlainSchemaRepoExtImpl.java | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java index d7f253165b3..12113d96988 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java @@ -22,13 +22,12 @@ import jakarta.persistence.Query; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO; -import org.apache.syncope.core.persistence.api.dao.NotFoundException; import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO; import org.apache.syncope.core.persistence.api.entity.AnyUtils; import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory; import org.apache.syncope.core.persistence.api.entity.PlainAttrValue; import org.apache.syncope.core.persistence.api.entity.PlainSchema; -import org.apache.syncope.core.persistence.jpa.dao.OracleJPAAnySearchDAO; +import org.apache.syncope.core.persistence.common.dao.AbstractSearchDAO; import org.apache.syncope.core.persistence.jpa.dao.SearchSupport; import org.apache.syncope.core.persistence.jpa.entity.JPARealm; @@ -37,6 +36,15 @@ public class OraclePlainSchemaRepoExtImpl extends AbstractPlainSchemaRepoExt { protected static final String HAS_ATTRS_QUERY = "SELECT COUNT(id) AS counts FROM %TABLE% " + "WHERE JSON_EXISTS(plainAttrs, '$[*]?(@.schema == \"%SCHEMA%\")')"; + protected static String hasAttrQueryWithValue(final String table, final PlainSchema schema) { + return new StringBuilder("SELECT COUNT(id) FROM "). + append(table). + append(" WHERE JSON_EXISTS(plainAttrs, '$[*]?(@.schema == \""). + append(schema.getKey()).append("\" && @.uniqueValue.").append(AbstractSearchDAO.key(schema.getType())). + append(" == $value)' PASSING ?1 AS \"value\") AND id <> ?2"). + toString(); + } + protected final PlainSchemaDAO plainSchemaDAO; public OraclePlainSchemaRepoExtImpl( @@ -60,16 +68,8 @@ public boolean existsPlainAttrUniqueValue( final PlainSchema schema, final PlainAttrValue attrValue) { - Query query = entityManager.createNativeQuery( - "SELECT COUNT(id) FROM " - + JPARealm.TABLE + "," - + OracleJPAAnySearchDAO.from(plainSchemaDAO.findById(schema.getKey()). - orElseThrow(() -> new NotFoundException("PlainSchema " + schema.getKey()))) - + " WHERE " + schema.getKey() + ".uniqueValue=?1 AND id <> ?2"); - query.setParameter(1, attrValue.getValue()); - query.setParameter(2, realmKey); - - return ((Number) query.getSingleResult()).longValue() > 0; + return doExistsPlainAttrUniqueValue(JPARealm.TABLE, schema, + attrValue.getValue(), realmKey); } @Override @@ -79,14 +79,17 @@ public boolean existsPlainAttrUniqueValue( final PlainSchema schema, final PlainAttrValue attrValue) { - Query query = entityManager.createNativeQuery( - "SELECT COUNT(id) FROM " - + new SearchSupport(anyUtils.anyTypeKind()).table().name() + "," - + OracleJPAAnySearchDAO.from(plainSchemaDAO.findById(schema.getKey()). - orElseThrow(() -> new NotFoundException("PlainSchema " + schema.getKey()))) - + " WHERE " + schema.getKey() + ".uniqueValue=?1 AND id <> ?2"); - query.setParameter(1, attrValue.getValue()); - query.setParameter(2, anyKey); + return doExistsPlainAttrUniqueValue(new SearchSupport(anyUtils.anyTypeKind()).table().name(), schema, + attrValue.getValue(), anyKey); + } + + protected boolean doExistsPlainAttrUniqueValue(final String table, final PlainSchema schema, + final String attrValue, final String attrKey) { + + Query query = entityManager.createNativeQuery(hasAttrQueryWithValue(table, schema)); + + query.setParameter(1, attrValue); + query.setParameter(2, attrKey); return ((Number) query.getSingleResult()).longValue() > 0; } From 0bdc76476f68fdf98761229cd921d7bdca7e2b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francesco=20Chicchiricc=C3=B2?= Date: Fri, 10 Jul 2026 16:00:35 +0200 Subject: [PATCH 2/4] Reflow --- .../jpa/OraclePersistenceContext.java | 3 +- .../repo/OraclePlainSchemaRepoExtImpl.java | 62 ++++++++++--------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/OraclePersistenceContext.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/OraclePersistenceContext.java index d49afa29b47..99b5ebacf30 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/OraclePersistenceContext.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/OraclePersistenceContext.java @@ -103,9 +103,8 @@ public RealmSearchDAO realmSearchDAO( public PlainSchemaRepoExt plainSchemaRepoExt( final AnyUtilsFactory anyUtilsFactory, final @Lazy ExternalResourceDAO resourceDAO, - final @Lazy PlainSchemaDAO plainSchemaDAO, final EntityManager entityManager) { - return new OraclePlainSchemaRepoExtImpl(anyUtilsFactory, resourceDAO, plainSchemaDAO, entityManager); + return new OraclePlainSchemaRepoExtImpl(anyUtilsFactory, resourceDAO, entityManager); } } diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java index 12113d96988..37e9183fb43 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java @@ -22,12 +22,11 @@ import jakarta.persistence.Query; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO; -import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO; import org.apache.syncope.core.persistence.api.entity.AnyUtils; import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory; import org.apache.syncope.core.persistence.api.entity.PlainAttrValue; import org.apache.syncope.core.persistence.api.entity.PlainSchema; -import org.apache.syncope.core.persistence.common.dao.AbstractSearchDAO; +import org.apache.syncope.core.persistence.jpa.dao.OracleJPAAnySearchDAO; import org.apache.syncope.core.persistence.jpa.dao.SearchSupport; import org.apache.syncope.core.persistence.jpa.entity.JPARealm; @@ -36,25 +35,12 @@ public class OraclePlainSchemaRepoExtImpl extends AbstractPlainSchemaRepoExt { protected static final String HAS_ATTRS_QUERY = "SELECT COUNT(id) AS counts FROM %TABLE% " + "WHERE JSON_EXISTS(plainAttrs, '$[*]?(@.schema == \"%SCHEMA%\")')"; - protected static String hasAttrQueryWithValue(final String table, final PlainSchema schema) { - return new StringBuilder("SELECT COUNT(id) FROM "). - append(table). - append(" WHERE JSON_EXISTS(plainAttrs, '$[*]?(@.schema == \""). - append(schema.getKey()).append("\" && @.uniqueValue.").append(AbstractSearchDAO.key(schema.getType())). - append(" == $value)' PASSING ?1 AS \"value\") AND id <> ?2"). - toString(); - } - - protected final PlainSchemaDAO plainSchemaDAO; - public OraclePlainSchemaRepoExtImpl( final AnyUtilsFactory anyUtilsFactory, final ExternalResourceDAO resourceDAO, - final PlainSchemaDAO plainSchemaDAO, final EntityManager entityManager) { super(anyUtilsFactory, resourceDAO, entityManager); - this.plainSchemaDAO = plainSchemaDAO; } @Override @@ -62,14 +48,38 @@ public boolean hasAttrs(final PlainSchema schema) { return hasAttrs(schema, HAS_ATTRS_QUERY, StringUtils.EMPTY); } + protected boolean existsPlainAttrUniqueValue( + final String table, + final PlainSchema schema, + final String attrValue, + final String attrKey) { + + String queryString = new StringBuilder("SELECT COUNT(id) FROM ").append(table). + append(" WHERE "). + append("JSON_EXISTS(plainAttrs, '$[*]?(@.schema == \"").append(schema.getKey()).append("\" "). + append("&& @.uniqueValue.").append(OracleJPAAnySearchDAO.key(schema.getType())).append(" == $value)' "). + append("PASSING ?1 AS \"value\") AND id <> ?2"). + toString(); + + Query query = entityManager.createNativeQuery(queryString); + + query.setParameter(1, attrValue); + query.setParameter(2, attrKey); + + return ((Number) query.getSingleResult()).longValue() > 0; + } + @Override public boolean existsPlainAttrUniqueValue( final String realmKey, final PlainSchema schema, final PlainAttrValue attrValue) { - return doExistsPlainAttrUniqueValue(JPARealm.TABLE, schema, - attrValue.getValue(), realmKey); + return existsPlainAttrUniqueValue( + JPARealm.TABLE, + schema, + attrValue.getValue(), + realmKey); } @Override @@ -79,18 +89,10 @@ public boolean existsPlainAttrUniqueValue( final PlainSchema schema, final PlainAttrValue attrValue) { - return doExistsPlainAttrUniqueValue(new SearchSupport(anyUtils.anyTypeKind()).table().name(), schema, - attrValue.getValue(), anyKey); - } - - protected boolean doExistsPlainAttrUniqueValue(final String table, final PlainSchema schema, - final String attrValue, final String attrKey) { - - Query query = entityManager.createNativeQuery(hasAttrQueryWithValue(table, schema)); - - query.setParameter(1, attrValue); - query.setParameter(2, attrKey); - - return ((Number) query.getSingleResult()).longValue() > 0; + return existsPlainAttrUniqueValue( + new SearchSupport(anyUtils.anyTypeKind()).table().name(), + schema, + attrValue.getValue(), + anyKey); } } From fa243c93d2f42581702ae998cac0bf17b7e5b66a Mon Sep 17 00:00:00 2001 From: vcrescia Date: Fri, 10 Jul 2026 18:00:38 +0200 Subject: [PATCH 3/4] Fix tests --- .../jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java index 37e9183fb43..51050bb4f83 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java @@ -78,7 +78,7 @@ public boolean existsPlainAttrUniqueValue( return existsPlainAttrUniqueValue( JPARealm.TABLE, schema, - attrValue.getValue(), + attrValue.getValue().toString(), realmKey); } @@ -92,7 +92,7 @@ public boolean existsPlainAttrUniqueValue( return existsPlainAttrUniqueValue( new SearchSupport(anyUtils.anyTypeKind()).table().name(), schema, - attrValue.getValue(), + attrValue.getValue().toString(), anyKey); } } From b718a1ac9ff70b90fe089e5ba59fe0429f8ef6dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francesco=20Chicchiricc=C3=B2?= Date: Sat, 11 Jul 2026 08:24:44 +0200 Subject: [PATCH 4/4] Fixing param conversion --- .../jpa/dao/OracleJPAAnySearchDAO.java | 2 +- .../dao/repo/OraclePlainSchemaRepoExtImpl.java | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OracleJPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OracleJPAAnySearchDAO.java index bf2dedc0715..7c847053600 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OracleJPAAnySearchDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/OracleJPAAnySearchDAO.java @@ -49,7 +49,7 @@ public class OracleJPAAnySearchDAO extends AbstractJPAAnySearchDAO { * or JSON_TABLE(plainAttrs, '$[*]?(@.schema == "loginDate").values[*]' \ * COLUMNS valuez PATH '$.dateValue') AS loginDate */ - public static String from(final PlainSchema schema) { + protected static String from(final PlainSchema schema) { return new StringBuilder("JSON_TABLE(plainAttrs, '$[*]?(@.schema == \"").append(schema.getKey()).append("\")."). append(schema.isUniqueConstraint() ? "uniqueValue" : "values[*]"). append("' COLUMNS ").append(schema.isUniqueConstraint() ? "uniqueValue" : "valuez"). diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java index 51050bb4f83..f056e9d082c 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/OraclePlainSchemaRepoExtImpl.java @@ -29,6 +29,7 @@ import org.apache.syncope.core.persistence.jpa.dao.OracleJPAAnySearchDAO; import org.apache.syncope.core.persistence.jpa.dao.SearchSupport; import org.apache.syncope.core.persistence.jpa.entity.JPARealm; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; public class OraclePlainSchemaRepoExtImpl extends AbstractPlainSchemaRepoExt { @@ -50,9 +51,9 @@ public boolean hasAttrs(final PlainSchema schema) { protected boolean existsPlainAttrUniqueValue( final String table, + final String key, final PlainSchema schema, - final String attrValue, - final String attrKey) { + final PlainAttrValue attrValue) { String queryString = new StringBuilder("SELECT COUNT(id) FROM ").append(table). append(" WHERE "). @@ -63,8 +64,9 @@ protected boolean existsPlainAttrUniqueValue( Query query = entityManager.createNativeQuery(queryString); - query.setParameter(1, attrValue); - query.setParameter(2, attrKey); + query.setParameter(1, StringUtils.stripEnd(StringUtils.stripStart( + POJOHelper.serialize(attrValue.getValue()), "\""), "\"")); + query.setParameter(2, key); return ((Number) query.getSingleResult()).longValue() > 0; } @@ -77,9 +79,9 @@ public boolean existsPlainAttrUniqueValue( return existsPlainAttrUniqueValue( JPARealm.TABLE, + realmKey, schema, - attrValue.getValue().toString(), - realmKey); + attrValue); } @Override @@ -91,8 +93,8 @@ public boolean existsPlainAttrUniqueValue( return existsPlainAttrUniqueValue( new SearchSupport(anyUtils.anyTypeKind()).table().name(), + anyKey, schema, - attrValue.getValue().toString(), - anyKey); + attrValue); } }