Package org.teiid.query.processor.relational

Source Code of org.teiid.query.processor.relational.NestedTableJoinStrategy

/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/

package org.teiid.query.processor.relational;

import java.util.List;
import java.util.Map;

import org.teiid.common.buffer.IndexedTupleSource;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.query.eval.Evaluator;
import org.teiid.query.processor.relational.SourceState.ImplicitBuffer;
import org.teiid.query.sql.lang.JoinType;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.util.SymbolMap;

/**
* Variation of a nested loop join that handles nested tables
*/
public class NestedTableJoinStrategy extends JoinStrategy {
 
  private SymbolMap leftMap;
  private SymbolMap rightMap;
  private Evaluator eval;
  private boolean outerMatched;

  @Override
  public NestedTableJoinStrategy clone() {
    NestedTableJoinStrategy clone = new NestedTableJoinStrategy();
    clone.leftMap = leftMap;
    clone.rightMap = rightMap;
    return clone;
  }
 
  @Override
  public void initialize(JoinNode joinNode) {
    super.initialize(joinNode);
    this.eval = new Evaluator(null, joinNode.getDataManager(), joinNode.getContext());
  }
 
  public void setLeftMap(SymbolMap leftMap) {
    this.leftMap = leftMap;
  }
 
  public void setRightMap(SymbolMap rightMap) {
    this.rightMap = rightMap;
  }
 
  @Override
  protected void openLeft() throws TeiidComponentException,
      TeiidProcessingException {
    if (leftMap == null) {
      super.openLeft();
    }
  }
 
  @Override
  protected void openRight() throws TeiidComponentException,
      TeiidProcessingException {
    if (rightMap == null) {
      super.openRight();
      this.rightSource.setImplicitBuffer(ImplicitBuffer.FULL);
    }
  }
 
  @Override
  protected void process() throws TeiidComponentException,
      TeiidProcessingException {
   
    if (leftMap != null && !leftSource.open) {
      for (Map.Entry<ElementSymbol, Expression> entry : leftMap.asMap().entrySet()) {
        joinNode.getContext().getVariableContext().setValue(entry.getKey(), eval.evaluate(entry.getValue(), null));
      }
      leftSource.getSource().reset();
      super.openLeft();
    }
   
    IndexedTupleSource its = leftSource.getIterator();
   
    while (its.hasNext() || leftSource.getCurrentTuple() != null) {
     
      List<?> leftTuple = leftSource.getCurrentTuple();
      if (leftTuple == null) {
        leftTuple = leftSource.saveNext();
      }
      updateContext(leftTuple, leftSource.getSource().getElements());
     
      if (rightMap != null && !rightSource.open) {
        for (Map.Entry<ElementSymbol, Expression> entry : rightMap.asMap().entrySet()) {
          joinNode.getContext().getVariableContext().setValue(entry.getKey(), eval.evaluate(entry.getValue(), null));
        }
        rightSource.getSource().reset();
        super.openRight();
      }
     
      IndexedTupleSource right = rightSource.getIterator();
     
      while (right.hasNext() || rightSource.getCurrentTuple() != null) {
       
        List<?> rightTuple = rightSource.getCurrentTuple();
        if (rightTuple == null) {
          rightTuple = rightSource.saveNext();
        }
       
        List<?> outputTuple = outputTuple(this.leftSource.getCurrentTuple(), this.rightSource.getCurrentTuple());
               
                boolean matches = this.joinNode.matchesCriteria(outputTuple);
               
                rightSource.saveNext();

                if (matches) {
                  outerMatched = true;
                  joinNode.addBatchRow(outputTuple);
                }
      }
     
      if (!outerMatched && this.joinNode.getJoinType() == JoinType.JOIN_LEFT_OUTER) {
              joinNode.addBatchRow(outputTuple(this.leftSource.getCurrentTuple(), this.rightSource.getOuterVals()));
            }
     
      outerMatched = false;
     
      if (rightMap == null) {
        rightSource.getIterator().setPosition(1);
      } else {
        rightSource.close();
        for (Map.Entry<ElementSymbol, Expression> entry : rightMap.asMap().entrySet()) {
          joinNode.getContext().getVariableContext().remove(entry.getKey());
        }
      }
     
      leftSource.saveNext();
      updateContext(null, leftSource.getSource().getElements());
    }
   
    if (leftMap != null) {
      leftSource.close();
      for (Map.Entry<ElementSymbol, Expression> entry : leftMap.asMap().entrySet()) {
        joinNode.getContext().getVariableContext().remove(entry.getKey());
      }
    }
  }

  private void updateContext(List<?> tuple,
      List<SingleElementSymbol> elements) {
    for (int i = 0; i < elements.size(); i++) {
      SingleElementSymbol element = elements.get(i);
      if (element instanceof ElementSymbol) {
        if (tuple == null) {
          joinNode.getContext().getVariableContext().remove((ElementSymbol)element);
        } else {
          joinNode.getContext().getVariableContext().setValue((ElementSymbol)element, tuple.get(i));
        }
      }
    }
  }
 
    public String toString() {
        return "NESTED TABLE JOIN"; //$NON-NLS-1$
    }

}
TOP

Related Classes of org.teiid.query.processor.relational.NestedTableJoinStrategy

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.