From cc8f117dfe87523d2b05606fd283404aac156f3d Mon Sep 17 00:00:00 2001 From: Jurgen <5031427+Jugen@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:43:45 +0200 Subject: [PATCH] Use an IN clause for single field disjoint ID prefetch --- .../access/HierarchicalObjectResolver.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) 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 a9f6a0f791..934c8ed032 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 @@ public boolean startDisjointByIdPrefetch(PrefetchTreeNode node) { private void createDisjointByIdPrefetchQualifier(String pathPrefix, PrefetchSelectQuery currentQuery, List joins, Set> 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 joinValues : values) {