Package org.apache.tajo.engine.planner.physical

Source Code of org.apache.tajo.engine.planner.physical.BNLJoinExec

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.tajo.engine.planner.physical;

import org.apache.tajo.worker.TaskAttemptContext;
import org.apache.tajo.engine.eval.EvalContext;
import org.apache.tajo.engine.eval.EvalNode;
import org.apache.tajo.engine.planner.logical.JoinNode;
import org.apache.tajo.engine.utils.SchemaUtil;
import org.apache.tajo.storage.FrameTuple;
import org.apache.tajo.storage.RowStoreUtil;
import org.apache.tajo.storage.Tuple;
import org.apache.tajo.storage.VTuple;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class BNLJoinExec extends BinaryPhysicalExec {
  // from logical plan
  private JoinNode plan;
  private EvalNode joinQual;
  private EvalContext qualCtx;

  private final List<Tuple> outerTupleSlots;
  private final List<Tuple> innerTupleSlots;
  private Iterator<Tuple> outerIterator;
  private Iterator<Tuple> innerIterator;

  private boolean innerEnd;
  private boolean outerEnd;

  // temporal tuples and states for nested loop join
  private FrameTuple frameTuple;
  private Tuple outerTuple = null;
  private Tuple outputTuple = null;
  private Tuple innext = null;

  private final int TUPLE_SLOT_SIZE = 10000;

  // projection
  private final int[] targetIds;

  public BNLJoinExec(final TaskAttemptContext context, final JoinNode plan,
                     final PhysicalExec outer, PhysicalExec inner) {
    super(context, SchemaUtil.merge(outer.getSchema(), inner.getSchema()), plan.getOutSchema(), outer, inner);
    this.plan = plan;
    this.joinQual = plan.getJoinQual();
    if (joinQual != null) { // if join type is not 'cross join'
      this.qualCtx = this.joinQual.newContext();
    }
    this.outerTupleSlots = new ArrayList<Tuple>(TUPLE_SLOT_SIZE);
    this.innerTupleSlots = new ArrayList<Tuple>(TUPLE_SLOT_SIZE);
    this.outerIterator = outerTupleSlots.iterator();
    this.innerIterator = innerTupleSlots.iterator();
    this.innerEnd = false;
    this.outerEnd = false;

    // for projection
    targetIds = RowStoreUtil.getTargetIds(inSchema, outSchema);

    // for join
    frameTuple = new FrameTuple();
    outputTuple = new VTuple(outSchema.getColumnNum());
  }

  public JoinNode getPlan() {
    return plan;
  }

  public Tuple next() throws IOException {

    if (outerTupleSlots.isEmpty()) {
      for (int k = 0; k < TUPLE_SLOT_SIZE; k++) {
        Tuple t = leftChild.next();
        if (t == null) {
          outerEnd = true;
          break;
        }
        outerTupleSlots.add(t);
      }
      outerIterator = outerTupleSlots.iterator();
      outerTuple = outerIterator.next();
    }

    if (innerTupleSlots.isEmpty()) {
      for (int k = 0; k < TUPLE_SLOT_SIZE; k++) {
        Tuple t = rightChild.next();
        if (t == null) {
          innerEnd = true;
          break;
        }
        innerTupleSlots.add(t);
      }
      innerIterator = innerTupleSlots.iterator();
    }

    if((innext = rightChild.next()) == null){
      innerEnd = true;
    }

    while (true) {
      if (!innerIterator.hasNext()) { // if inneriterator ended
        if (outerIterator.hasNext()) { // if outertupleslot remains
          outerTuple = outerIterator.next();
          innerIterator = innerTupleSlots.iterator();
        } else {
          if (innerEnd) {
            rightChild.rescan();
            innerEnd = false;
           
            if (outerEnd) {
              return null;
            }
            outerTupleSlots.clear();
            for (int k = 0; k < TUPLE_SLOT_SIZE; k++) {
              Tuple t = leftChild.next();
              if (t == null) {
                outerEnd = true;
                break;
              }
              outerTupleSlots.add(t);
            }
            if (outerTupleSlots.isEmpty()) {
              return null;
            }
            outerIterator = outerTupleSlots.iterator();
            outerTuple = outerIterator.next();
           
          } else {
            outerIterator = outerTupleSlots.iterator();
            outerTuple = outerIterator.next();
          }
         
          innerTupleSlots.clear();
          if (innext != null) {
            innerTupleSlots.add(innext);
            for (int k = 1; k < TUPLE_SLOT_SIZE; k++) { // fill inner
              Tuple t = rightChild.next();
              if (t == null) {
                innerEnd = true;
                break;
              }
              innerTupleSlots.add(t);
            }
          } else {
            for (int k = 0; k < TUPLE_SLOT_SIZE; k++) { // fill inner
              Tuple t = rightChild.next();
              if (t == null) {
                innerEnd = true;
                break;
              }
              innerTupleSlots.add(t);
            }
          }
         
          if ((innext = rightChild.next()) == null) {
            innerEnd = true;
          }
          innerIterator = innerTupleSlots.iterator();
        }
      }

      frameTuple.set(outerTuple, innerIterator.next());
      if (joinQual != null) {
        joinQual.eval(qualCtx, inSchema, frameTuple);
        if (joinQual.terminate(qualCtx).asBool()) {
          RowStoreUtil.project(frameTuple, outputTuple, targetIds);
          return outputTuple;
        }
      } else {
        RowStoreUtil.project(frameTuple, outputTuple, targetIds);
        return outputTuple;
      }
    }
  }

  @Override
  public void rescan() throws IOException {
    super.rescan();
    innerEnd = false;
    innerTupleSlots.clear();
    outerTupleSlots.clear();
    innerIterator = innerTupleSlots.iterator();
    outerIterator = outerTupleSlots.iterator();
  }
}
TOP

Related Classes of org.apache.tajo.engine.planner.physical.BNLJoinExec

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.