rubenada commented on a change in pull request #1614: [CALCITE-3546] Improve 
EnumerableDefaults nested loop join
URL: https://github.com/apache/calcite/pull/1614#discussion_r352023673
 
 

 ##########
 File path: 
linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
 ##########
 @@ -1852,6 +1866,104 @@ private boolean innerHasNext() {
     return Linq4j.asEnumerable(result);
   }
 
+  /**
+   * Implementation of nested loop join that, unlike {@link 
#nestedLoopJoinAsList}, does not
+   * require to build the complete result as a list before returning it. 
Instead, it iterates
+   * through the outer enumerable and inner enumerable and returns the results 
step by step.
+   * It does not support RIGHT / FULL join.
+   */
+  private static <TSource, TInner, TResult> Enumerable<TResult> 
nestedLoopJoinOptimized(
+      final Enumerable<TSource> outer, final Enumerable<TInner> inner,
+      final Predicate2<TSource, TInner> predicate,
+      Function2<TSource, TInner, TResult> resultSelector,
+      final JoinType joinType) {
+    if (joinType == JoinType.RIGHT || joinType == JoinType.FULL) {
+      throw new IllegalArgumentException("JoinType " + joinType + " is 
unsupported");
+    }
+
+    return new AbstractEnumerable<TResult>() {
+      public Enumerator<TResult> enumerator() {
+        return new Enumerator<TResult>() {
+          private Enumerator<TSource> outerEnumerator = outer.enumerator();
+          private Enumerator<TInner> innerEnumerator = null;
+          private boolean outerMatch = false; // whether the outerValue has 
matched an innerValue
+          private TSource outerValue;
+          private TInner innerValue;
+          private int state = 0; // 0 moving outer, 1 moving inner
+
+          @Override public TResult current() {
+            return resultSelector.apply(outerValue, innerValue);
+          }
+
+          @Override public boolean moveNext() {
+            while (true) {
+              switch (state) {
+              case 0:
+                // move outer
+                if (!outerEnumerator.moveNext()) {
+                  return false;
+                }
+                outerValue = outerEnumerator.current();
+                if (innerEnumerator != null) {
+                  innerEnumerator.close();
+                }
+                innerEnumerator = inner.enumerator();
+                outerMatch = false;
+                state = 1;
+                continue;
+              case 1:
+                // move inner
+                if (innerEnumerator.moveNext()) {
+                  innerValue = innerEnumerator.current();
+                  if (predicate.apply(outerValue, innerValue)) {
+                    outerMatch = true;
+                    switch (joinType) {
+                    case ANTI: // try next outer row
+                      state = 0;
+                      continue;
+                    case SEMI: // return result, and try next outer row
+                      state = 0;
+                      // fall through
+                    default: // INNER and LEFT just return result
 
 Review comment:
   Ok, it will make it clearer. Change committed.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to