@@ -59,7 +59,10 @@ TupleExpr buildSegmentRoot(Deque<TupleExpr> orderedArgs, List<DeferredFilter> fi
5959 prefixBindingNames .addAll (optimized .getBindingNames ());
6060 }
6161 List <DeferredFilter > unresolvedFilters = new ArrayList <>();
62- for (DeferredFilter filter : LmdbJoinPlanSupport .sortDeferredFilters (pendingFilters )) {
62+ List <DeferredFilter > sortedFilters = LmdbJoinPlanSupport .sortDeferredFilters (pendingFilters );
63+ while (!sortedFilters .isEmpty ()) {
64+ int filterIndex = nextDeferredFilterIndex (factors , sortedFilters , boundBeforeSegment );
65+ DeferredFilter filter = sortedFilters .remove (filterIndex );
6366 if (!groupDeferredFilterOnSmallestWindow (factors , filter , boundBeforeSegment )) {
6467 unresolvedFilters .add (filter );
6568 }
@@ -76,6 +79,45 @@ TupleExpr buildSegmentRoot(Deque<TupleExpr> orderedArgs, List<DeferredFilter> fi
7679 return root ;
7780 }
7881
82+ private int nextDeferredFilterIndex (List <SegmentFactor > factors , List <DeferredFilter > sortedFilters ,
83+ Set <String > boundBeforeSegment ) {
84+ int bestIndex = -1 ;
85+ BindingAssignmentWindow bestWindow = null ;
86+ for (int i = 0 ; i < sortedFilters .size (); i ++) {
87+ DeferredFilter filter = sortedFilters .get (i );
88+ if (LmdbJoinPlanSupport .containsExists (filter .condition )) {
89+ continue ;
90+ }
91+ BindingAssignmentWindow window = bindingAssignmentCoveringWindow (factors , filter , boundBeforeSegment );
92+ if (window == null ) {
93+ continue ;
94+ }
95+ if (bestWindow == null || compareBindingAssignmentWindow (window , filter , bestWindow ,
96+ sortedFilters .get (bestIndex )) < 0 ) {
97+ bestIndex = i ;
98+ bestWindow = window ;
99+ }
100+ }
101+ return bestIndex < 0 ? 0 : bestIndex ;
102+ }
103+
104+ private int compareBindingAssignmentWindow (BindingAssignmentWindow left , DeferredFilter leftFilter ,
105+ BindingAssignmentWindow right , DeferredFilter rightFilter ) {
106+ int endComparison = Integer .compare (left .endIndex , right .endIndex );
107+ if (endComparison != 0 ) {
108+ return endComparison ;
109+ }
110+ int spanComparison = Integer .compare (left .endIndex - left .startIndex , right .endIndex - right .startIndex );
111+ if (spanComparison != 0 ) {
112+ return spanComparison ;
113+ }
114+ int costComparison = Integer .compare (leftFilter .conditionCost , rightFilter .conditionCost );
115+ if (costComparison != 0 ) {
116+ return costComparison ;
117+ }
118+ return Integer .compare (leftFilter .originalIndex , rightFilter .originalIndex );
119+ }
120+
79121 private TupleExpr applyPrefixBindingDeferredFilters (TupleExpr tupleExpr ,
80122 List <DeferredFilter > deferredFilters , Set <String > prefixBindingNames ,
81123 Set <StatementPattern > currentPatterns , Set <StatementPattern > remainingPatterns ) {
@@ -201,10 +243,35 @@ private int[] smallestSinglePatternBindingCoveringWindow(List<SegmentFactor> fac
201243
202244 private boolean groupDeferredFilterOnBindingAssignments (List <SegmentFactor > factors ,
203245 DeferredFilter deferredFilter , Set <String > boundBeforeSegment ) {
246+ BindingAssignmentWindow window = bindingAssignmentCoveringWindow (factors , deferredFilter , boundBeforeSegment );
247+ if (window == null ) {
248+ return false ;
249+ }
250+
251+ Deque <TupleExpr > selectedRoots = new ArrayDeque <>(window .selectedIndexes .size ());
252+ Set <StatementPattern > containedPatterns = LmdbJoinPlanSupport .identityPatternSet ();
253+ for (Integer selectedIndex : window .selectedIndexes ) {
254+ SegmentFactor factor = factors .get (selectedIndex );
255+ selectedRoots .addLast (factor .tupleExpr );
256+ containedPatterns .addAll (factor .containedPatterns );
257+ }
258+ TupleExpr filteredRoot = filterWrapper .wrap (buildJoinRoot (selectedRoots ), List .of (deferredFilter ),
259+ "bindingAssignments" );
260+ SegmentFactor groupedFactor = new SegmentFactor (filteredRoot , containedPatterns );
261+ int insertionIndex = window .startIndex ;
262+ for (int i = window .selectedIndexes .size () - 1 ; i >= 0 ; i --) {
263+ factors .remove ((int ) window .selectedIndexes .get (i ));
264+ }
265+ factors .add (insertionIndex , groupedFactor );
266+ return true ;
267+ }
268+
269+ private BindingAssignmentWindow bindingAssignmentCoveringWindow (List <SegmentFactor > factors ,
270+ DeferredFilter deferredFilter , Set <String > boundBeforeSegment ) {
204271 Set <String > missingVars = new HashSet <>(deferredFilter .requiredVars );
205272 missingVars .removeAll (boundBeforeSegment );
206273 if (missingVars .isEmpty ()) {
207- return false ;
274+ return null ;
208275 }
209276
210277 List <Integer > selectedIndexes = new ArrayList <>();
@@ -217,29 +284,10 @@ private boolean groupDeferredFilterOnBindingAssignments(List<SegmentFactor> fact
217284 selectedIndexes .add (i );
218285 missingVars .removeAll (factor .bindingNames );
219286 if (missingVars .isEmpty ()) {
220- break ;
287+ return new BindingAssignmentWindow ( selectedIndexes ) ;
221288 }
222289 }
223- if (!missingVars .isEmpty () || selectedIndexes .isEmpty ()) {
224- return false ;
225- }
226-
227- Deque <TupleExpr > selectedRoots = new ArrayDeque <>(selectedIndexes .size ());
228- Set <StatementPattern > containedPatterns = LmdbJoinPlanSupport .identityPatternSet ();
229- for (Integer selectedIndex : selectedIndexes ) {
230- SegmentFactor factor = factors .get (selectedIndex );
231- selectedRoots .addLast (factor .tupleExpr );
232- containedPatterns .addAll (factor .containedPatterns );
233- }
234- TupleExpr filteredRoot = filterWrapper .wrap (buildJoinRoot (selectedRoots ), List .of (deferredFilter ),
235- "bindingAssignments" );
236- SegmentFactor groupedFactor = new SegmentFactor (filteredRoot , containedPatterns );
237- int insertionIndex = selectedIndexes .get (0 );
238- for (int i = selectedIndexes .size () - 1 ; i >= 0 ; i --) {
239- factors .remove ((int ) selectedIndexes .get (i ));
240- }
241- factors .add (insertionIndex , groupedFactor );
242- return true ;
290+ return null ;
243291 }
244292
245293 private boolean groupDeferredFilterOnWindow (List <SegmentFactor > factors , DeferredFilter filter , int [] window ) {
@@ -322,4 +370,16 @@ private TupleExpr buildJoinRoot(Deque<TupleExpr> orderedArgs) {
322370 }
323371 return root ;
324372 }
373+
374+ private static final class BindingAssignmentWindow {
375+ private final List <Integer > selectedIndexes ;
376+ private final int startIndex ;
377+ private final int endIndex ;
378+
379+ private BindingAssignmentWindow (List <Integer > selectedIndexes ) {
380+ this .selectedIndexes = selectedIndexes ;
381+ this .startIndex = selectedIndexes .get (0 );
382+ this .endIndex = selectedIndexes .get (selectedIndexes .size () - 1 );
383+ }
384+ }
325385}
0 commit comments