Package org.apache.derby.impl.sql.compile

Source Code of org.apache.derby.impl.sql.compile.IndexToBaseRowNode

/*

   Derby - Class org.apache.derby.impl.sql.compile.IndexToBaseRowNode

   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.derby.impl.sql.compile;

import org.apache.derby.iapi.services.context.ContextManager;

import org.apache.derby.iapi.sql.compile.AccessPath;
import org.apache.derby.iapi.sql.compile.CostEstimate;
import org.apache.derby.iapi.sql.compile.Optimizable;

import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;

import org.apache.derby.impl.sql.compile.ActivationClassBuilder;

import org.apache.derby.iapi.error.StandardException;

import org.apache.derby.iapi.services.compiler.MethodBuilder;

import org.apache.derby.iapi.sql.execute.NoPutResultSet;

import org.apache.derby.iapi.sql.Activation;
import org.apache.derby.iapi.sql.ResultSet;

import org.apache.derby.iapi.services.loader.GeneratedMethod;

import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;

import org.apache.derby.iapi.services.io.FormatableBitSet;

import org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl;
import org.apache.derby.iapi.reference.ClassName;
import org.apache.derby.iapi.services.classfile.VMOpcode;

import java.util.Properties;
import java.util.Vector;

/**
* This node type translates an index row to a base row.  It takes a
* FromBaseTable as its source ResultSetNode, and generates an
* IndexRowToBaseRowResultSet that takes a TableScanResultSet on an
* index conglomerate as its source.
*/
public class IndexToBaseRowNode extends FromTable
{
  protected FromBaseTable  source;
  protected ConglomerateDescriptor  baseCD;
  protected boolean  cursorTargetTable;
  protected PredicateList restrictionList;
  protected boolean  forUpdate;
  private FormatableBitSet  heapReferencedCols;
  private FormatableBitSet  indexReferencedCols;
  private FormatableBitSet  allReferencedCols;
  private FormatableBitSet  heapOnlyReferencedCols;

  public void init(
      Object  source,
      Object  baseCD,
      Object  resultColumns,
      Object  cursorTargetTable,
      Object heapReferencedCols,
      Object indexReferencedCols,
      Object restrictionList,
      Object forUpdate,
      Object tableProperties)
  {
    super.init(null, tableProperties);
    this.source = (FromBaseTable) source;
    this.baseCD = (ConglomerateDescriptor) baseCD;
    this.resultColumns = (ResultColumnList) resultColumns;
    this.cursorTargetTable = ((Boolean) cursorTargetTable).booleanValue();
    this.restrictionList = (PredicateList) restrictionList;
    this.forUpdate = ((Boolean) forUpdate).booleanValue();
    this.heapReferencedCols = (FormatableBitSet) heapReferencedCols;
    this.indexReferencedCols = (FormatableBitSet) indexReferencedCols;

    if (this.indexReferencedCols == null) {
      this.allReferencedCols = this.heapReferencedCols;
      heapOnlyReferencedCols = this.heapReferencedCols;
    }
    else {
      this.allReferencedCols =
        new FormatableBitSet(this.heapReferencedCols);
      this.allReferencedCols.or(this.indexReferencedCols);
      heapOnlyReferencedCols =
        new FormatableBitSet(allReferencedCols);
      heapOnlyReferencedCols.xor(this.indexReferencedCols);
    }
  }

  /** @see Optimizable#forUpdate */
  public boolean forUpdate()
  {
    return source.forUpdate();
  }

  /** @see Optimizable#getTrulyTheBestAccessPath */
  public AccessPath getTrulyTheBestAccessPath()
  {
    // Get AccessPath comes from base table.
    return ((Optimizable) source).getTrulyTheBestAccessPath();
  }

  public CostEstimate getCostEstimate()
  {
    return source.getTrulyTheBestAccessPath().getCostEstimate();
  }

  public CostEstimate getFinalCostEstimate()
  {
    return source.getFinalCostEstimate();
  }

  /**
   * Return whether or not the underlying ResultSet tree
   * is ordered on the specified columns.
   * RESOLVE - This method currently only considers the outermost table
   * of the query block.
   *
   * @param  crs          The specified ColumnReference[]
   * @param  permuteOrdering    Whether or not the order of the CRs in the array can be permuted
   * @param  fbtVector      Vector that is to be filled with the FromBaseTable 
   *
   * @return  Whether the underlying ResultSet tree
   * is ordered on the specified column.
   *
   * @exception StandardException    Thrown on error
   */
  boolean isOrderedOn(ColumnReference[] crs, boolean permuteOrdering, Vector fbtVector)
        throws StandardException
  {
    return source.isOrderedOn(crs, permuteOrdering, fbtVector);
  }

  /**
   * Generation of an IndexToBaseRowNode creates an
   * IndexRowToBaseRowResultSet, which uses the RowLocation in the last
   * column of an index row to get the row from the base conglomerate (heap).
   *
   * @param acb  The ActivationClassBuilder for the class being built
   * @param mb the method  for the method to be built
   *
   * @exception StandardException    Thrown on error
   */
  public void generate(ActivationClassBuilder acb,
                MethodBuilder mb)
              throws StandardException
  {
    ValueNode    restriction = null;

    /*
    ** Get the next ResultSet #, so that we can number this ResultSetNode,
    ** its ResultColumnList and ResultSet.
    */
    assignResultSetNumber();

    // Get the CostEstimate info for the underlying scan
    costEstimate = getFinalCostEstimate();

    /* Put the predicates back into the tree */
    if (restrictionList != null)
    {
      restriction = restrictionList.restorePredicates();
      /* Allow the restrictionList to get garbage collected now
       * that we're done with it.
       */
      restrictionList = null;
    }

    // for the restriction, we generate an exprFun
    // that evaluates the expression of the clause
    // against the current row of the child's result.
    // if the restriction is empty, simply pass null
    // to optimize for run time performance.

       // generate the function and initializer:
       // Note: Boolean lets us return nulls (boolean would not)
       // private Boolean exprN()
       // {
       //   return <<restriction.generate(ps)>>;
       // }
       // static Method exprN = method pointer to exprN;



    int heapColRefItem = -1;
    if (heapReferencedCols != null)
    {
      heapColRefItem = acb.addItem(heapReferencedCols);
    }
    int allColRefItem = -1;
    if (allReferencedCols != null)
    {
      allColRefItem = acb.addItem(allReferencedCols);
    }
    int heapOnlyColRefItem = -1;
    if (heapOnlyReferencedCols != null)
    {
      heapOnlyColRefItem = acb.addItem(heapOnlyReferencedCols);
    }

    /* Create the ReferencedColumnsDescriptorImpl which tells which columns
     * come from the index.
     */
    int indexColMapItem = acb.addItem(new ReferencedColumnsDescriptorImpl(getIndexColMapping()));
    long heapConglomNumber = baseCD.getConglomerateNumber();
    StaticCompiledOpenConglomInfo scoci = getLanguageConnectionContext().
                        getTransactionCompile().
                          getStaticCompiledConglomInfo(heapConglomNumber);

    acb.pushGetResultSetFactoryExpression(mb);

    mb.push(heapConglomNumber);
    mb.push(acb.addItem(scoci));
    source.generate(acb, mb);
   
    mb.upCast(ClassName.NoPutResultSet);

    resultColumns.generateHolder(acb, mb,  heapReferencedCols, indexReferencedCols);
    mb.push(resultSetNumber);
    mb.push(source.getBaseTableName());
    mb.push(heapColRefItem);

    mb.push(allColRefItem);
    mb.push(heapOnlyColRefItem);

    mb.push(indexColMapItem);

    // if there is no restriction, we just want to pass null.
    if (restriction == null)
    {
         mb.pushNull(ClassName.GeneratedMethod);
    }
    else
    {
      // this sets up the method and the static field.
      // generates:
      //   Object userExprFun { }
      MethodBuilder userExprFun = acb.newUserExprFun();

      // restriction knows it is returning its value;
 
      /* generates:
       *    return <restriction.generate(acb)>;
       * and adds it to userExprFun
       * NOTE: The explicit cast to DataValueDescriptor is required
       * since the restriction may simply be a boolean column or subquery
       * which returns a boolean.  For example:
       *    where booleanColumn
       */
      restriction.generate(acb, userExprFun);
      userExprFun.methodReturn();

      // we are done modifying userExprFun, complete it.
      userExprFun.complete();

         // restriction is used in the final result set as an access of the new static
         // field holding a reference to this new method.
      // generates:
      //  ActivationClass.userExprFun
      // which is the static field that "points" to the userExprFun
      // that evaluates the where clause.
         acb.pushMethodReference(mb, userExprFun);
    }

    mb.push(forUpdate);
    mb.push(costEstimate.rowCount());
    mb.push(costEstimate.getEstimatedCost());

    mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getIndexRowToBaseRowResultSet",
            ClassName.NoPutResultSet, 14);

    /* The IndexRowToBaseRowResultSet generator is what we return */

    /*
    ** Remember if this result set is the cursor target table, so we
    ** can know which table to use when doing positioned update and delete.
    */
    if (cursorTargetTable)
    {
      acb.rememberCursorTarget(mb);
    }
  }

  /**
   * Return whether or not the underlying ResultSet tree will return
   * a single row, at most.
   * This is important for join nodes where we can save the extra next
   * on the right side if we know that it will return at most 1 row.
   *
   * @return Whether or not the underlying ResultSet tree will return a single row.
   * @exception StandardException    Thrown on error
   */
  public boolean isOneRowResultSet()  throws StandardException
  {
    // Default is false
    return source.isOneRowResultSet();
  }

  /**
   * Return whether or not the underlying FBT is for NOT EXISTS.
   *
   * @return Whether or not the underlying FBT is for NOT EXISTS.
   */
  public boolean isNotExists()
  {
    return source.isNotExists();
  }

  /**
   * Decrement (query block) level (0-based) for this FromTable.
   * This is useful when flattening a subquery.
   *
   * @param decrement  The amount to decrement by.
   */
  void decrementLevel(int decrement)
  {
    source.decrementLevel(decrement);
  }

  /**
   * Get the lock mode for the target of an update statement
   * (a delete or update).  The update mode will always be row for
   * CurrentOfNodes.  It will be table if there is no where clause.
   *
   * @return  The lock mode
   */
  public int updateTargetLockMode()
  {
    return source.updateTargetLockMode();
  }

  /**
   * @see ResultSetNode#adjustForSortElimination
   */
  void adjustForSortElimination()
  {
    /* NOTE: We use a different method to tell a FBT that
     * it cannot do a bulk fetch as the ordering issues are
     * specific to a FBT being under an IRTBR as opposed to a
     * FBT being under a PRN, etc.
     */
    source.disableBulkFetch();
  }

  /**
   * Fill in the column mapping for those columns coming from the index.
   *
   * @return The int[] with the mapping.
   */
  private int[] getIndexColMapping()
  {
    int    rclSize = resultColumns.size();
    int[]  indexColMapping = new int[rclSize];

    for (int index = 0; index < rclSize; index++)
    {
      ResultColumn rc = (ResultColumn) resultColumns.elementAt(index);
      if (indexReferencedCols != null && rc.getExpression() instanceof VirtualColumnNode)
      {
        // Column is coming from index
        VirtualColumnNode vcn = (VirtualColumnNode) rc.getExpression();
        indexColMapping[index] =
          vcn.getSourceColumn().getVirtualColumnId() - 1;
      }
      else
      {
        // Column is not coming from index
        indexColMapping[index] = -1;
      }
    }

    return indexColMapping;
  }

}
TOP

Related Classes of org.apache.derby.impl.sql.compile.IndexToBaseRowNode

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.