Merge pull request #606 from Jugen/use-in-clause-for-single-field-disjoint-by-id-prefetches
CAY-2843 Use an IN clause for single field disjoint by ID prefetches
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 5b07858..1658d19 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -63,6 +63,7 @@
CAY-2831 Upgrade Gradle to 8.5
CAY-2834 v11 upgrade handler should update XMLPoolingDataSourceFactory package
CAY-2837 Deprecate TraversalHelper and move no-op implementations to TraversalHandler
+CAY-2843 Use an IN clause for single field disjoint by ID prefetches
Bug Fixes:
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java b/cayenne/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
index a9f6a0f..934c8ed 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
@@ -38,6 +38,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* Processes a number of DataRow sets corresponding to a given prefetch tree, resolving
@@ -205,8 +206,19 @@
private void createDisjointByIdPrefetchQualifier(String pathPrefix, PrefetchSelectQuery<?> currentQuery,
List<DbJoin> joins, Set<List<Object>> values) {
- Expression allJoinsQualifier;
- if(currentQuery != null) {
+ if (currentQuery == null) return;
+
+ // Use an IN clause for the list of prefetch IDs, when the
+ // join ON clause only has one predicate with many values.
+ // Results in SQL: ... targetField IN ( ?, ?, ?, .... )
+ if (joins.size() == 1 && values.size() > 1) {
+ currentQuery.and( ExpressionFactory.inDbExp(
+ pathPrefix + joins.get(0).getTargetName(),
+ values.stream().flatMap(List::stream).collect(Collectors.toSet())
+ ));
+ } else { // Handle a single value or compound prefetch ID predicates
+ // SQL: ... (field1=? and field2=? ...) OR (field1=? and field2=? ...) etc
+ Expression allJoinsQualifier;
Expression[] qualifiers = new Expression[values.size()];
int i = 0;
for(List<Object> joinValues : values) {