@@ -1966,13 +1966,19 @@ static <TSource, TInner, TKey, TNsKey, TResult> Enumerable<TResult> leftMarkHash
19661966 }
19671967
19681968 /**
1969- * For each row of the {@code outer} enumerable returns correlated rows
1970- * from the inner enumerable generated for each outer row, filtered by a predicate
1971- * (correlated LEFT_MARK join).
1969+ * The implementation of left mark join based on nested loop.
1970+ * This is a unified implementation supporting both correlated and non-correlated cases.
1971+ *
1972+ * @param outer Left input
1973+ * @param innerProvider Function that provides inner enumerable for each outer row
1974+ * (for correlated join, pass outerRow -> correlatedInner)
1975+ * (for non-correlated join, pass outerRow -> staticInner)
1976+ * @param predicate Non-equi predicate that can return NULL
1977+ * @param resultSelector Function that concats the row of left input and marker
19721978 */
1973- public static <TSource , TInner , TResult > Enumerable <TResult > correlateLeftMarkJoin (
1979+ private static <TSource , TInner , TResult > Enumerable <TResult > leftMarkJoinInternal (
19741980 final Enumerable <TSource > outer ,
1975- final Function1 <TSource , Enumerable <TInner >> inner ,
1981+ final Function1 <TSource , Enumerable <TInner >> innerProvider ,
19761982 final NullablePredicate2 <TSource , TInner > predicate ,
19771983 final Function2 <TSource , @ Nullable Boolean , TResult > resultSelector ) {
19781984 return new AbstractEnumerable <TResult >() {
@@ -1991,7 +1997,7 @@ public static <TSource, TInner, TResult> Enumerable<TResult> correlateLeftMarkJo
19911997 }
19921998 marker = false ;
19931999 final TSource outerRow = outers .current ();
1994- Enumerable <TInner > innerEnumerable = inner .apply (outerRow );
2000+ Enumerable <TInner > innerEnumerable = innerProvider .apply (outerRow );
19952001 if (innerEnumerable != null ) {
19962002 try (Enumerator <TInner > inners = innerEnumerable .enumerator ()) {
19972003 while (inners .moveNext ()) {
@@ -2021,6 +2027,19 @@ public static <TSource, TInner, TResult> Enumerable<TResult> correlateLeftMarkJo
20212027 };
20222028 }
20232029
2030+ /**
2031+ * For each row of the {@code outer} enumerable returns correlated rows
2032+ * from the inner enumerable generated for each outer row, filtered by a predicate
2033+ * (correlated LEFT_MARK join).
2034+ */
2035+ public static <TSource , TInner , TResult > Enumerable <TResult > correlateLeftMarkJoin (
2036+ final Enumerable <TSource > outer ,
2037+ final Function1 <TSource , Enumerable <TInner >> inner ,
2038+ final NullablePredicate2 <TSource , TInner > predicate ,
2039+ final Function2 <TSource , @ Nullable Boolean , TResult > resultSelector ) {
2040+ return leftMarkJoinInternal (outer , inner , predicate , resultSelector );
2041+ }
2042+
20242043 /**
20252044 * The implementation of left mark join based on nested loop.
20262045 *
@@ -2033,47 +2052,7 @@ public static <TSource, TInner, TResult> Enumerable<TResult> leftMarkNestedLoopJ
20332052 final Enumerable <TSource > outer , final Enumerable <TInner > inner ,
20342053 final NullablePredicate2 <TSource , TInner > predicate ,
20352054 final Function2 <TSource , @ Nullable Boolean , TResult > resultSelector ) {
2036- return new AbstractEnumerable <TResult >() {
2037- @ Override public Enumerator <TResult > enumerator () {
2038- return new Enumerator <TResult >() {
2039- Enumerator <TSource > outers = outer .enumerator ();
2040- @ Nullable Boolean marker = false ;
2041-
2042- @ Override public TResult current () {
2043- return resultSelector .apply (outers .current (), marker );
2044- }
2045-
2046- @ Override public boolean moveNext () {
2047- if (!outers .moveNext ()) {
2048- return false ;
2049- }
2050- marker = false ;
2051- final TSource outerRow = outers .current ();
2052- try (Enumerator <TInner > inners = inner .enumerator ()) {
2053- while (inners .moveNext ()) {
2054- final TInner innerRow = inners .current ();
2055- Boolean predicateMatched = predicate .apply (outerRow , innerRow );
2056- if (predicateMatched == null ) {
2057- marker = null ;
2058- } else if (predicateMatched ) {
2059- marker = true ;
2060- break ;
2061- }
2062- }
2063- }
2064- return true ;
2065- }
2066-
2067- @ Override public void reset () {
2068- outers .reset ();
2069- }
2070-
2071- @ Override public void close () {
2072- outers .close ();
2073- }
2074- };
2075- }
2076- };
2055+ return leftMarkJoinInternal (outer , ignored -> inner , predicate , resultSelector );
20772056 }
20782057
20792058 /**
0 commit comments