use of org.apache.derby.iapi.util.JBitSet in project derby by apache.
the class FromSubquery method extractSubquery.
/**
* Extract out and return the subquery, with a PRN on top.
* (See FromSubquery.preprocess() for more details.)
*
* @param numTables The number of tables in the DML Statement
*
* @return ResultSetNode at top of extracted tree.
*
* @exception StandardException Thrown on error
*/
ResultSetNode extractSubquery(int numTables) throws StandardException {
JBitSet newJBS;
ResultSetNode newPRN;
newPRN = new ProjectRestrictNode(subquery, /* Child ResultSet */
getResultColumns(), /* Projection */
null, /* Restriction */
null, /* Restriction as PredicateList */
null, /* Subquerys in Projection */
null, /* Subquerys in Restriction */
tableProperties, getContextManager());
/* Set up the PRN's referencedTableMap */
newJBS = new JBitSet(numTables);
newJBS.set(tableNumber);
newPRN.setReferencedTableMap(newJBS);
((FromTable) newPRN).setTableNumber(tableNumber);
return newPRN;
}
use of org.apache.derby.iapi.util.JBitSet in project derby by apache.
the class FromVTI method legalJoinOrder.
/**
* @see Optimizable#legalJoinOrder
*/
@Override
public boolean legalJoinOrder(JBitSet assignedTableMap) {
/* In order to tell if this is a legal join order, we
* need to see if the assignedTableMap, ORed with the
* outer tables that we are correlated with, contains
* our dependency map.
*/
JBitSet tempBitSet = assignedTableMap;
tempBitSet.or(correlationMap);
/* Have all of our dependencies been satisified? */
return tempBitSet.contains(dependencyMap);
}
use of org.apache.derby.iapi.util.JBitSet in project derby by apache.
the class FromVTI method preprocess.
/**
* Preprocess a ResultSetNode - this currently means:
* o Generating a referenced table map for each ResultSetNode.
* o Putting the WHERE and HAVING clauses in conjunctive normal form (CNF).
* o Converting the WHERE and HAVING clauses into PredicateLists and
* classifying them.
* o Ensuring that a ProjectRestrictNode is generated on top of every
* FromBaseTable and generated in place of every FromSubquery.
* o Pushing single table predicates down to the new ProjectRestrictNodes.
*
* @param numTables The number of tables in the DML Statement
* @param gbl The group by list, if any
* @param fromList The from list, if any
*
* @return ResultSetNode at top of preprocessed tree.
*
* @exception StandardException Thrown on error
*/
@Override
ResultSetNode preprocess(int numTables, GroupByList gbl, FromList fromList) throws StandardException {
methodCall.preprocess(numTables, new FromList(getOptimizerFactory().doJoinOrderOptimization(), getContextManager()), new SubqueryList(getContextManager()), new PredicateList(getContextManager()));
/* Generate the referenced table map */
setReferencedTableMap(new JBitSet(numTables));
getReferencedTableMap().set(tableNumber);
/* Create the dependency map. This FromVTI depends on any
* tables which are referenced by the method call. Note,
* though, that such tables should NOT appear in this node's
* referencedTableMap, since that field is really meant to
* hold the table numbers for any FromTables which appear
* AT OR UNDER the subtree whose root is this FromVTI. That
* said, the tables referenced by methodCall do not appear
* "under" this FromVTI--on the contrary, they must appear
* "above" this FromVTI within the query tree in order to
* be referenced by the methodCall. So methodCall table
* references do _not_ belong in this.referencedTableMap.
* (DERBY-3288)
*/
dependencyMap = new JBitSet(numTables);
methodCall.categorize(dependencyMap, false);
// Make sure this FromVTI does not "depend" on itself.
dependencyMap.clear(tableNumber);
// Get a JBitSet of the outer tables represented in the parameter list
correlationMap = new JBitSet(numTables);
methodCall.getCorrelationTables(correlationMap);
return genProjectRestrict(numTables);
}
use of org.apache.derby.iapi.util.JBitSet in project derby by apache.
the class HalfOuterJoinNode method transformOuterJoins.
/**
* Transform any Outer Join into an Inner Join where applicable.
* (Based on the existence of a null intolerant
* predicate on the inner table.)
*
* @param predicateTree The predicate tree for the query block
*
* @return The new tree top (OuterJoin or InnerJoin).
*
* @exception StandardException Thrown on error
*/
@Override
FromTable transformOuterJoins(ValueNode predicateTree, int numTables) throws StandardException {
ResultSetNode innerRS;
if (predicateTree == null) {
/* We can't transform this node, so tell both sides of the
* outer join that they can't get flattened into outer query block.
*/
leftResultSet.notFlattenableJoin();
rightResultSet.notFlattenableJoin();
return this;
}
super.transformOuterJoins(predicateTree, numTables);
if (rightOuterJoin) {
if (SanityManager.DEBUG) {
SanityManager.ASSERT(!transformed, "right OJ not expected to be transformed into left OJ yet");
}
innerRS = leftResultSet;
} else {
innerRS = rightResultSet;
}
// We a relooking for a null intolerant predicate on an inner table.
// Collect base table numbers, also if they are located inside a join
// (inner or outer), that is, the inner operand is itself a join,
// recursively.
JBitSet innerMap = innerRS.LOJgetReferencedTables(numTables);
/* Walk predicates looking for
* a null intolerant predicate on the inner table.
*/
ValueNode vn = predicateTree;
while (vn instanceof AndNode) {
AndNode and = (AndNode) vn;
ValueNode left = and.getLeftOperand();
/* Skip IS NULL predicates as they are not null intolerant */
if (left.getClass().equals(IsNullNode.class) && ((IsNullNode) left).isNullNode()) {
vn = and.getRightOperand();
continue;
}
/* Only consider predicates that are relops */
if (left instanceof RelationalOperator) {
JBitSet refMap = new JBitSet(numTables);
/* Do not consider method calls,
* conditionals, field references, etc. */
if (!(left.categorize(refMap, true))) {
vn = and.getRightOperand();
continue;
}
/* If the predicate is a null intolerant predicate
* on the right side then we can flatten to an
* inner join. We do the xform here, flattening
* will happen later.
*/
for (int bit = 0; bit < numTables; bit++) {
if (refMap.get(bit) && innerMap.get(bit)) {
// OJ -> IJ
JoinNode ij = new JoinNode(leftResultSet, rightResultSet, joinClause, null, getResultColumns(), null, null, getContextManager());
ij.setTableNumber(tableNumber);
ij.setSubqueryList(subqueryList);
ij.setAggregates(aggregates);
return ij;
}
}
}
vn = and.getRightOperand();
}
/* We can't transform this node, so tell both sides of the
* outer join that they can't get flattened into outer query block.
*/
leftResultSet.notFlattenableJoin();
rightResultSet.notFlattenableJoin();
return this;
}
use of org.apache.derby.iapi.util.JBitSet in project derby by apache.
the class HalfOuterJoinNode method LOJ_reorderable.
/**
* This method recursively:
* <ul>
* <li>determines if this part of the query tree is a compound OJ of
* the shape required for reordering and if so,</li>
* <li>does a reordering.</li>
* </ul>
* <pre>
*
* OJ1 pT1T2 OJ1 pT2T3
* / \ / \
* / \ can / t3
* t1 OJ2 pT2T3 reorder /
* / \ to OJ2 pT1T2
* / \ / \
* t2 t3 / \
* t1 t2
*
* where pR1R2 is a null-rejecting predicate which references the schema
* of joinee R1 and R2, cf. terminology explanation in #isNullRejecting.
* <p/>
* OJ1 represents <em>this</em> before and after the reordering.
* </pre>
* <p/>
* The join predicates are assumed to be in CNF form.
* <p/>
* <em>Note:</em> Present implementation limitations
* <ul>
* <li>Only left outer joins are considered, i.e. both OJs in diagram
* above must be LOJ.</li>
* <li>Top left side must be a base table (t1 above). The bottow right
* side
* (t3 above) may be another OJ, so reordering can happen
* recursively.</li>
* </ul>
*
* @param numTables number of tables involved (needed to right size the
* bitmaps)
* @return boolean true if any reordering took place at this level or deeper
* so caller can know whether rebinding may be necessary
* @throws StandardException standard error policy
*/
@Override
boolean LOJ_reorderable(int numTables) throws StandardException {
boolean anyChange = false;
// row-preserving side
ResultSetNode logicalLeftResultSet;
// null-producing side
ResultSetNode logicalRightResultSet;
// null-producing side.
if (rightOuterJoin) {
// right outer join
logicalLeftResultSet = rightResultSet;
logicalRightResultSet = leftResultSet;
} else {
logicalLeftResultSet = leftResultSet;
logicalRightResultSet = rightResultSet;
}
// Redundantly normalize the ON predicate (it will also be called in preprocess()).
super.normExpressions();
// This is a very simple OJ of base tables. Do nothing.
if (logicalLeftResultSet instanceof FromBaseTable && logicalRightResultSet instanceof FromBaseTable)
return anyChange;
// table references need to be recomputed.
if (logicalLeftResultSet instanceof HalfOuterJoinNode) {
anyChange = ((HalfOuterJoinNode) logicalLeftResultSet).LOJ_reorderable(numTables) || anyChange;
} else if (!(logicalLeftResultSet instanceof FromBaseTable)) {
// select * from v8 left outer join (s left outer join r on (f = i)) on (e=v8.bv);
return anyChange;
}
if (logicalRightResultSet instanceof HalfOuterJoinNode) {
anyChange = ((HalfOuterJoinNode) logicalRightResultSet).LOJ_reorderable(numTables) || anyChange;
} else if (!(logicalRightResultSet instanceof FromBaseTable)) {
// right operand must be either a base table or another OJ
return anyChange;
}
// into LOJ alread. So, we skip optimizing ROJ at the moment.
if (rightOuterJoin || (logicalRightResultSet instanceof HalfOuterJoinNode && ((HalfOuterJoinNode) logicalRightResultSet).rightOuterJoin)) {
return LOJ_bindResultColumns(anyChange);
}
// Build the data structure for testing/doing OJ reordering. Fill in
// the table references on row-preserving and null-producing sides. It
// may be possible that either operand is a complex view.
// Row-preserving
JBitSet RPReferencedTableMap;
// Null-producing
JBitSet NPReferencedTableMap;
RPReferencedTableMap = logicalLeftResultSet.LOJgetReferencedTables(numTables);
NPReferencedTableMap = logicalRightResultSet.LOJgetReferencedTables(numTables);
if ((RPReferencedTableMap == null || NPReferencedTableMap == null) && anyChange) {
return LOJ_bindResultColumns(anyChange);
}
// to push the join.
if (logicalRightResultSet instanceof HalfOuterJoinNode) {
// Get the row-preserving map of the child OJ
JBitSet nestedChildOJRPRefTableMap = ((HalfOuterJoinNode) logicalRightResultSet).LOJgetRPReferencedTables(numTables);
// Checks that top has p(t1,t2)
if (!isNullRejecting(joinClause, RPReferencedTableMap, nestedChildOJRPRefTableMap)) {
// No, give up.
return LOJ_bindResultColumns(anyChange);
}
// Get the null-producing map of the child OJ
JBitSet nestedChildOJNPRefTableMap = ((HalfOuterJoinNode) logicalRightResultSet).LOJgetNPReferencedTables(numTables);
// Checks that right child has p(t2,t3)
if (isNullRejecting(((HalfOuterJoinNode) logicalRightResultSet).joinClause, nestedChildOJRPRefTableMap, nestedChildOJNPRefTableMap)) {
// before we proceed.
if (super.subqueryList.size() != 0 || ((JoinNode) logicalRightResultSet).subqueryList.size() != 0 || super.joinPredicates.size() != 0 || ((JoinNode) logicalRightResultSet).joinPredicates.size() != 0 || super.usingClause != null || ((JoinNode) logicalRightResultSet).usingClause != null) {
// get out of here
return LOJ_bindResultColumns(anyChange);
}
// we are reordering the OJs.
anyChange = true;
ResultSetNode tmp = logicalLeftResultSet;
ResultSetNode LChild, RChild;
// this OJ
// / \
// logicalLeftRS LogicalRightRS
// / \
// LChild RChild
// becomes
//
// this OJ
// / \
// LogicalRightRS RChild
// / \
// logicalLeftRS LChild <<< we need to be careful about this
// order as the "LogicalRightRS
// may be a ROJ
//
// handle the lower level OJ node
LChild = ((HalfOuterJoinNode) logicalRightResultSet).leftResultSet;
RChild = ((HalfOuterJoinNode) logicalRightResultSet).rightResultSet;
((HalfOuterJoinNode) logicalRightResultSet).rightResultSet = LChild;
((HalfOuterJoinNode) logicalRightResultSet).leftResultSet = tmp;
// switch the ON clause
{
ValueNode vn = joinClause;
joinClause = ((HalfOuterJoinNode) logicalRightResultSet).joinClause;
((HalfOuterJoinNode) logicalRightResultSet).joinClause = vn;
}
// No need to switch HalfOuterJoinNode data members for now
// because we are handling only OJ.
// boolean local_rightOuterJoin = rightOuterJoin;
// boolean local_transformed = transformed;
// rightOuterJoin = ((HalfOuterJoinNode)logicalRightResultSet).
// rightOuterJoin;
// transformed = ((HalfOuterJoinNode)logicalRightResultSet).
// transformed;
// ((HalfOuterJoinNode)logicalRightResultSet).rightOuterJoin =
// local_rightOuterJoin;
// ((HalfOuterJoinNode)logicalRightResultSet).transformed =
// local_transformed;
FromList localFromList = new FromList(getOptimizerFactory().doJoinOrderOptimization(), getContextManager());
// switch OJ nodes: by handling the current OJ node
leftResultSet = logicalRightResultSet;
rightResultSet = RChild;
// rebuild the result columns and re-bind column references
((HalfOuterJoinNode) leftResultSet).setResultColumns(null);
// localFromList is empty:
((JoinNode) leftResultSet).bindResultColumns(localFromList);
// left operand must be another OJ, so recurse.
boolean localChange = ((HalfOuterJoinNode) leftResultSet).LOJ_reorderable(numTables);
}
}
return LOJ_bindResultColumns(anyChange);
}
Aggregations