Search in sources :

Example 36 with JBitSet

use of org.apache.derby.iapi.util.JBitSet in project derby by apache.

the class FromList method legalJoinOrder.

/**
 * @see OptimizableList#legalJoinOrder
 */
public boolean legalJoinOrder(int numTablesInQuery) {
    JBitSet assignedTableMap = new JBitSet(numTablesInQuery);
    int size = size();
    for (int index = 0; index < size; index++) {
        FromTable ft = (FromTable) elementAt(index);
        assignedTableMap.or(ft.getReferencedTableMap());
        if (!ft.legalJoinOrder(assignedTableMap)) {
            return false;
        }
    }
    return true;
}
Also used : JBitSet(org.apache.derby.iapi.util.JBitSet)

Example 37 with JBitSet

use of org.apache.derby.iapi.util.JBitSet in project derby by apache.

the class JoinNode method pushExpressionsToRight.

private void pushExpressionsToRight(PredicateList outerPredicateList) throws StandardException {
    FromTable rightFromTable = (FromTable) rightResultSet;
    JBitSet rightReferencedTableMap = rightFromTable.getReferencedTableMap();
    // Walk outerPredicateList backwards due to possible deletes
    for (int index = outerPredicateList.size() - 1; index >= 0; index--) {
        Predicate predicate = outerPredicateList.elementAt(index);
        if (!predicate.getPushable()) {
            continue;
        }
        JBitSet curBitSet = predicate.getReferencedSet();
        /* Do we have a match? */
        if (rightReferencedTableMap.contains(curBitSet)) {
            /* Add the matching predicate to the push list */
            getRightPredicateList().addPredicate(predicate);
            /* Remap all of the ColumnReferences to point to the
				 * source of the values.
				 * The tree is something like:
				 *			PRN1
				 *			  |
				 *			 JN (this)
				 *		   /    \
				 *		PRN2	PRN3
				 *        |       |
				 *		FBT1	FBT2
				 *
				 * The ColumnReferences start off pointing to the RCL off of
				 * PRN1.  For optimization, we want them to point to the
				 * RCL off of PRN3.  In order to do that, we remap them
				 * twice here.  If optimization pushes them down to the
				 * base table, it will remap them again.
				 */
            RemapCRsVisitor rcrv = new RemapCRsVisitor(true);
            predicate.getAndNode().accept(rcrv);
            predicate.getAndNode().accept(rcrv);
            /* Remove the matching predicate from the outer list */
            outerPredicateList.removeElementAt(index);
        }
    }
}
Also used : JBitSet(org.apache.derby.iapi.util.JBitSet) OptimizablePredicate(org.apache.derby.iapi.sql.compile.OptimizablePredicate)

Example 38 with JBitSet

use of org.apache.derby.iapi.util.JBitSet in project derby by apache.

the class HashJoinStrategy method feasible.

/**
 * @see JoinStrategy#feasible
 *
 * @exception StandardException		Thrown on error
 */
public boolean feasible(Optimizable innerTable, OptimizablePredicateList predList, Optimizer optimizer) throws StandardException {
    ConglomerateDescriptor cd = null;
    /* If the innerTable is a VTI, then we
		 * must check to see if there are any
		 * join columns in the VTI's parameters.
		 * If so, then hash join is not feasible.
		 */
    if (!innerTable.isMaterializable()) {
        if (innerTable.optimizerTracingIsOn()) {
            innerTable.getOptimizerTracer().traceSkipUnmaterializableHashJoin();
        }
        return false;
    }
    /* Don't consider hash join on the target table of an update/delete.
		 * RESOLVE - this is a temporary restriction.  Problem is that we
		 * do not put RIDs into the row in the hash table when scanning
		 * the heap and we need them for a target table.
		 */
    if (innerTable.isTargetTable()) {
        return false;
    }
    /* If the predicate given by the user _directly_ references
		 * any of the base tables _beneath_ this node, then we
		 * cannot safely use the predicate for a hash because the
		 * predicate correlates two nodes at different nesting levels. 
		 * If we did a hash join in this case, materialization of
		 * innerTable could lead to incorrect results--and in particular,
		 * results that are missing rows.  We can check for this by
		 * looking at the predicates' reference maps, which are set based
		 * on the initial query (as part of pre-processing).  Note that
		 * by the time we get here, it's possible that a predicate's
		 * reference map holds table numbers that do not agree with the
		 * table numbers of the column references used by the predicate.
		 * That's okay--this occurs as a result of "remapping" predicates
		 * that have been pushed down the query tree.  And in fact
		 * it's a good thing because, by looking at the column reference's
		 * own table numbers instead of the predicate's referenced map,
		 * we are more readily able to find equijoin predicates that
		 * we otherwise would not have found.
		 *
		 * Note: do not perform this check if innerTable is a FromBaseTable
		 * because a base table does not have a "subtree" to speak of.
		 */
    if ((predList != null) && (predList.size() > 0) && !(innerTable instanceof FromBaseTable)) {
        FromTable ft = (FromTable) innerTable;
        // First get a list of all of the base tables in the subtree
        // below innerTable.
        JBitSet tNums = new JBitSet(ft.getReferencedTableMap().size());
        BaseTableNumbersVisitor btnVis = new BaseTableNumbersVisitor(tNums);
        ft.accept(btnVis);
        // Now get a list of all table numbers referenced by the
        // join predicates that we'll be searching.
        JBitSet pNums = new JBitSet(tNums.size());
        for (int i = 0; i < predList.size(); i++) {
            Predicate pred = (Predicate) predList.getOptPredicate(i);
            if (pred.isJoinPredicate())
                pNums.or(pred.getReferencedSet());
        }
        // If tNums and pNums have anything in common, then at
        // least one predicate in the list refers directly to
        // a base table beneath this node (as opposed to referring
        // just to this node), which means it's not safe to do a
        // hash join.
        tNums.and(pNums);
        if (tNums.getFirstSetBit() != -1)
            return false;
    }
    if (innerTable.isBaseTable()) {
        /* Must have an equijoin on a column in the conglomerate */
        cd = innerTable.getCurrentAccessPath().getConglomerateDescriptor();
    }
    /* Look for equijoins in the predicate list */
    int[] hashKeyColumns = findHashKeyColumns(innerTable, cd, predList);
    if (SanityManager.DEBUG) {
        if (innerTable.optimizerTracingIsOn()) {
            if (hashKeyColumns == null) {
                innerTable.getOptimizerTracer().traceSkipHashJoinNoHashKeys();
            } else {
                innerTable.getOptimizerTracer().traceHashKeyColumns(ArrayUtil.copy(hashKeyColumns));
            }
        }
    }
    if (hashKeyColumns == null) {
        return false;
    }
    return true;
}
Also used : JBitSet(org.apache.derby.iapi.util.JBitSet) ConglomerateDescriptor(org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor) OptimizablePredicate(org.apache.derby.iapi.sql.compile.OptimizablePredicate)

Example 39 with JBitSet

use of org.apache.derby.iapi.util.JBitSet in project derby by apache.

the class Predicate method getPredScopedForResultSet.

/**
 * If this predicate's operator is a BinaryRelationalOperatorNode,
 * then look at the operands and return a new, equivalent predicate
 * that is "scoped" to the received ResultSetNode.  By "scoped" we
 * mean that the operands, which shold be column references, have been
 * mapped to the appropriate result columns in the received RSN.
 * This is useful for pushing predicates from outer queries down
 * into inner queries, in which case the column references need
 * to be remapped.
 *
 * For example, let V1 represent
 *
 *    select i,j from t1 UNION select i,j from t2
 *
 * and V2 represent
 *
 *    select a,b from t3 UNION select a,b from t4
 *
 * Then assume we have the following query:
 *
 *    select * from V1, V2 where V1.j = V2.b
 *
 * Let's further assume that this Predicate object represents the
 * "V1.j = V2.b" operator and that the childRSN we received
 * as a parameter represents one of the subqueries to which we
 * want to push the predicate; let's say it's:
 *
 *    select i,j from t1
 *
 * Then this method will return a new predicate whose binary
 * operator represents the expression "T1.j = V2.b" (that is, V1.j
 * will be mapped to the corresponding column in T1).  For more on
 * how that mapping is made, see the "getScopedOperand()" method
 * in BinaryRelationalOperatorNode.java.
 *
 * ASSUMPTION: We should only get to this method if we know that
 * at least one operand in this predicate can and should be mapped
 * to the received childRSN.  For an example of where that check is
 * made, see the pushOptPredicate() method in SetOperatorNode.java.
 *
 * @param parentRSNsTables Set of all table numbers referenced by
 *  the ResultSetNode that is _parent_ to the received childRSN.
 *  We need this to make sure we don't scope the operands to a
 *  ResultSetNode to which they don't apply.
 * @param childRSN The result set node for which we want to create
 *  a scoped predicate.
 * @param whichRC If not -1 then this tells us which ResultColumn
 *  in the received childRSN we need to use for the scoped predicate;
 *  if -1 then the column position of the scoped column reference
 *  will be stored in this array and passed back to the caller.
 * @return A new predicate whose operands have been scoped to the
 *  received childRSN.
 */
protected Predicate getPredScopedForResultSet(JBitSet parentRSNsTables, ResultSetNode childRSN, int[] whichRC) throws StandardException {
    // We only deal with binary relational operators here.
    if (!(getAndNode().getLeftOperand() instanceof BinaryRelationalOperatorNode)) {
        return this;
    }
    // The predicate must have an AndNode in CNF, so we
    // need to create an AndNode representing:
    // <scoped_bin_rel_op> AND TRUE
    // First create the boolean constant for TRUE.
    ValueNode trueNode = new BooleanConstantNode(true, getContextManager());
    BinaryRelationalOperatorNode opNode = (BinaryRelationalOperatorNode) getAndNode().getLeftOperand();
    // Create a new op node with left and right operands that point
    // to the received result set's columns as appropriate.
    BinaryRelationalOperatorNode newOpNode = new BinaryRelationalOperatorNode(opNode.kind, opNode.getScopedOperand(BinaryRelationalOperatorNode.LEFT, parentRSNsTables, childRSN, whichRC), opNode.getScopedOperand(BinaryRelationalOperatorNode.RIGHT, parentRSNsTables, childRSN, whichRC), opNode.getForQueryRewrite(), getContextManager());
    // Bind the new op node.
    newOpNode.bindComparisonOperator();
    // Create and bind a new AND node in CNF form,
    // i.e. "<newOpNode> AND TRUE".
    AndNode newAnd = new AndNode(newOpNode, trueNode, getContextManager());
    newAnd.postBindFixup();
    // Categorize the new AND node; among other things, this
    // call sets up the new operators's referenced table map,
    // which is important for correct pushing of the new
    // predicate.
    JBitSet tableMap = new JBitSet(childRSN.getReferencedTableMap().size());
    newAnd.categorize(tableMap, false);
    // Now put the pieces together to get a new predicate.
    Predicate newPred = new Predicate(newAnd, tableMap, getContextManager());
    // Copy all of this predicates other fields into the new predicate.
    newPred.clearScanFlags();
    newPred.copyFields(this);
    newPred.setPushable(getPushable());
    // Take note of the fact that the new predicate is scoped for
    // the sake of pushing; we need this information during optimization
    // to figure out what we should and should not "pull" back up.
    newPred.markAsScopedForPush();
    return newPred;
}
Also used : JBitSet(org.apache.derby.iapi.util.JBitSet) OptimizablePredicate(org.apache.derby.iapi.sql.compile.OptimizablePredicate)

Aggregations

JBitSet (org.apache.derby.iapi.util.JBitSet)39 OptimizablePredicate (org.apache.derby.iapi.sql.compile.OptimizablePredicate)12 OptimizablePredicateList (org.apache.derby.iapi.sql.compile.OptimizablePredicateList)7 Optimizable (org.apache.derby.iapi.sql.compile.Optimizable)2 ConglomerateDescriptor (org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 IndexDescriptor (org.apache.derby.catalog.IndexDescriptor)1 ContextManager (org.apache.derby.iapi.services.context.ContextManager)1 FormatableBitSet (org.apache.derby.iapi.services.io.FormatableBitSet)1 CostEstimate (org.apache.derby.iapi.sql.compile.CostEstimate)1 DataValueDescriptor (org.apache.derby.iapi.types.DataValueDescriptor)1 StandardException (org.apache.derby.shared.common.error.StandardException)1