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;
}
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);
}
}
}
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;
}
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;
}
Aggregations