Package com.alvazan.orm.layer5.query

Source Code of com.alvazan.orm.layer5.query.CursorForAnd

package com.alvazan.orm.layer5.query;

import java.util.HashMap;
import java.util.Map;

import com.alvazan.orm.api.z5api.IndexColumnInfo;
import com.alvazan.orm.api.z8spi.conv.ByteArray;
import com.alvazan.orm.api.z8spi.conv.Precondition;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder;
import com.alvazan.orm.api.z8spi.iter.DirectCursor;
import com.alvazan.orm.api.z8spi.iter.StringLocal;
import com.alvazan.orm.api.z8spi.meta.ViewInfo;

public class CursorForAnd implements DirectCursor<IndexColumnInfo> {

  private DirectCursor<IndexColumnInfo> leftResults;
  private DirectCursor<IndexColumnInfo> rightResults;
  private ViewInfo leftView;
  private ViewInfo rightView;
  private Map<ByteArray, IndexColumnInfo> cachedMap;
  private boolean ranFullInnerLoopTo500Once = false;
 
  public CursorForAnd(ViewInfo leftView2, DirectCursor<IndexColumnInfo> leftResults,
      ViewInfo rightView2, DirectCursor<IndexColumnInfo> rightResults) {
    Precondition.check(leftView2, "leftView2");
    Precondition.check(leftResults, "leftResults");
    Precondition.check(rightView2, "rightView2");
    Precondition.check(rightResults, "rightResults");
    this.leftView = leftView2;
    this.rightView = rightView2;
    this.leftResults = leftResults;
    this.rightResults = rightResults;
  }

  @Override
  public String toString() {
    String tabs = StringLocal.getAndAdd();
    String retVal = "CursorForAnd["+tabs+leftResults+","+tabs+rightResults+tabs+"]";
    StringLocal.set(tabs.length());
    return retVal;
  }


  @Override
  public Holder<IndexColumnInfo> nextImpl() {
    while(true) {
      Holder<IndexColumnInfo> nextFromCursor = leftResults.nextImpl();
      if(nextFromCursor == null)
        break;
      IndexColumnInfo next = nextFromCursor.getValue();

      if(cachedMap != null) {
        Holder<IndexColumnInfo> result = quickHashLookup(next);
        if(result != null)
          return result;
      } else if(!ranFullInnerLoopTo500Once) {
        rightResults.beforeFirst();
        Holder<IndexColumnInfo> result = runFullInnerLoopOnce(next);
        if(result != null)
          return result;       
      } else {
        //Need to change to lookahead joining here as well as switch join types on the fly
        //This stinks as we have to re-read from the database every 1000 rows!!!! We should find out if
        //we can do any kind of counting or something so we don't have to go back to database every time
        rightResults.beforeFirst();
        Holder<IndexColumnInfo> result = runInnerLoop(next);
        if(result != null)
          return result;
      }
    }
    return null;
  }
 
  @Override
  public Holder<IndexColumnInfo> previousImpl() {
    while(true) {
      Holder<IndexColumnInfo> prevFromCursor = leftResults.previousImpl();
      if(prevFromCursor == null)
        break;
      IndexColumnInfo next = prevFromCursor.getValue();

      if(cachedMap != null) {
        Holder<IndexColumnInfo> result = quickHashLookup(next);
        if(result != null)
          return result;
      } else if(!ranFullInnerLoopTo500Once) {
        rightResults.afterLast();
        Holder<IndexColumnInfo> result = runFullInnerLoopOnceBackward(next);
        if(result != null)
          return result;       
      } else {
        //Need to change to lookahead joining here as well as switch join types on the fly
        //This stinks as we have to re-read from the database every 1000 rows!!!! We should find out if
        //we can do any kind of counting or something so we don't have to go back to database every time
        rightResults.afterLast();
        Holder<IndexColumnInfo> result = runInnerLoopBackward(next);
        if(result != null)
          return result;
      }
    }
    return null;
  }

  private Holder<IndexColumnInfo> runFullInnerLoopOnce(IndexColumnInfo next) {
    Map<ByteArray, IndexColumnInfo> pkToRightSide = new HashMap<ByteArray, IndexColumnInfo>();
    Holder<IndexColumnInfo> matchedResult = null;
    while(true) {
      Holder<IndexColumnInfo> nextFromCursor = rightResults.nextImpl();
      if(nextFromCursor == null)
        break;
      IndexColumnInfo andedInfo = nextFromCursor.getValue();
      ByteArray key1 = next.getPrimaryKey(leftView);
      ByteArray key2 = andedInfo.getPrimaryKey(rightView);
      if(pkToRightSide.size() < 500)
        pkToRightSide.put(key2, andedInfo);
      if(matchedResult == null && key1.equals(key2)) {
        next.mergeResults(andedInfo);
        matchedResult = new Holder<IndexColumnInfo>(next);
      }
     
      if(matchedResult != null && pkToRightSide.size()>=500) {
        //we have exceeded cache size so we can't switch to a Hash join :(
        return matchedResult;
      }
    }
   
    if(pkToRightSide.size() < 500)
      cachedMap = pkToRightSide;
    return matchedResult;
  }
 
  private Holder<IndexColumnInfo> runFullInnerLoopOnceBackward(IndexColumnInfo previous) {
    Map<ByteArray, IndexColumnInfo> pkToRightSide = new HashMap<ByteArray, IndexColumnInfo>();
    Holder<IndexColumnInfo> matchedResult = null;
    while(true) {
      Holder<IndexColumnInfo> previousFromCursor = rightResults.previousImpl();
      if(previousFromCursor == null)
        break;
      IndexColumnInfo andedInfo = previousFromCursor.getValue();
      ByteArray key1 = previous.getPrimaryKey(leftView);
      ByteArray key2 = andedInfo.getPrimaryKey(rightView);
      if(pkToRightSide.size() < 500)
        pkToRightSide.put(key2, andedInfo);
      if(matchedResult == null && key1.equals(key2)) {
        previous.mergeResults(andedInfo);
        matchedResult = new Holder<IndexColumnInfo>(previous);
      }
     
      if(matchedResult != null && pkToRightSide.size()>=500) {
        //we have exceeded cache size so we can't switch to a Hash join :(
        return matchedResult;
      }
    }
   
    if(pkToRightSide.size() < 500)
      cachedMap = pkToRightSide;
    return matchedResult;
  }


  private Holder<IndexColumnInfo> quickHashLookup(IndexColumnInfo next) {
    ByteArray key1 = next.getPrimaryKey(leftView);
    IndexColumnInfo andedInfo = cachedMap.get(key1);
    if(andedInfo == null)
      return null;
    next.mergeResults(andedInfo);
    return new Holder<IndexColumnInfo>(next);
  }

  private Holder<IndexColumnInfo> runInnerLoop(IndexColumnInfo next) {
    while(true) {
      Holder<IndexColumnInfo> nextFromCursor = rightResults.nextImpl();
      if(nextFromCursor == null)
        break;
      IndexColumnInfo andedInfo = nextFromCursor.getValue();
      ByteArray key1 = next.getPrimaryKey(leftView);
      ByteArray key2 = andedInfo.getPrimaryKey(rightView);
      if(key1.equals(key2)) {
        next.mergeResults(andedInfo);
        return new Holder<IndexColumnInfo>(next);
      }
    }
   
    return null;
  }
 
  private Holder<IndexColumnInfo> runInnerLoopBackward(IndexColumnInfo previous) {
    while(true) {
      Holder<IndexColumnInfo> prevFromCursor = rightResults.previousImpl();
      if(prevFromCursor == null)
        break;
      IndexColumnInfo andedInfo = prevFromCursor.getValue();
      ByteArray key1 = previous.getPrimaryKey(leftView);
      ByteArray key2 = andedInfo.getPrimaryKey(rightView);
      if(key1.equals(key2)) {
        previous.mergeResults(andedInfo);
        return new Holder<IndexColumnInfo>(previous);
      }
    }
   
    return null;
  }


  @Override
  public void beforeFirst() {
    leftResults.beforeFirst();
    rightResults.beforeFirst();
  }
 
  @Override
  public void afterLast() {
    leftResults.afterLast();
    rightResults.afterLast();
  }

}
TOP

Related Classes of com.alvazan.orm.layer5.query.CursorForAnd

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.