}
// Build the data structure for testing/doing LOJ reordering.
// Fill in the table references on row-preserving and null-producing sides.
// It may be possible that either operand is a complex view.
JBitSet NPReferencedTableMap; // Null-producing
JBitSet RPReferencedTableMap; // Row-preserving
RPReferencedTableMap = logicalLeftResultSet.LOJgetReferencedTables(numTables);
NPReferencedTableMap = logicalRightResultSet.LOJgetReferencedTables(numTables);
if ((RPReferencedTableMap == null || NPReferencedTableMap == null) &&
anyChange)
{
return LOJ_bindResultColumns(anyChange);
}
// Check if the predicate is equality predicate in CNF (i.e., AND only)
// and left/right column references must come from either operand.
// That is, we don't allow:
// 1. A=A
// 2. 1=1
// 3. B=C where both B and C are either from left or right operand.
// we probably need to make the joinClause "left-deep" so that we can
// walk it easier.
BinaryRelationalOperatorNode equals;
ValueNode leftCol;
ValueNode rightCol;
AndNode and;
ValueNode left;
ValueNode vn = joinClause;
while (vn instanceof AndNode)
{
and = (AndNode) vn;
left = and.getLeftOperand();
// Make sure that this is an equijoin of the form "C = D" where C
// and D references tables from both left and right operands.
if (left instanceof RelationalOperator &&
((ValueNode)left).isBinaryEqualsOperatorNode())
{
equals = (BinaryRelationalOperatorNode) left;
leftCol = equals.getLeftOperand();
rightCol = equals.getRightOperand();
if (!( leftCol instanceof ColumnReference && rightCol instanceof ColumnReference))
return LOJ_bindResultColumns(anyChange);
boolean refCheck = false;
boolean leftOperandCheck = false;
if (RPReferencedTableMap.get(((ColumnReference)leftCol).getTableNumber()))
{
refCheck = true;
leftOperandCheck = true;
}
else if (NPReferencedTableMap.get(((ColumnReference)leftCol).getTableNumber()))
{
refCheck = true;
}
if (refCheck == false)
return LOJ_bindResultColumns(anyChange);
refCheck = false;
if (leftOperandCheck == false && RPReferencedTableMap.get(((ColumnReference)rightCol).getTableNumber()))
{
refCheck = true;
}
else if (leftOperandCheck == true && NPReferencedTableMap.get(((ColumnReference)rightCol).getTableNumber()))
{
refCheck = true;
}
if (refCheck == false)
return LOJ_bindResultColumns(anyChange);
}
else return LOJ_bindResultColumns(anyChange); // get out of here
vn = and.getRightOperand();
}
// Check if the logical right resultset is a composite inner and as such
// that this current LOJ can be pushed through it.
boolean push = false;
// logical right operand is another LOJ... so we may be able to push the
// join
if (logicalRightResultSet instanceof HalfOuterJoinNode)
{
// get the Null-producing operand of the child
JBitSet logicalNPRefTableMap = ((HalfOuterJoinNode)logicalRightResultSet).LOJgetNPReferencedTables(numTables);
// does the current LOJ join predicate reference
// logicalNPRefTableMap? If not, we can push the current
// join.
vn = joinClause;
push = true;
while (vn instanceof AndNode)
{
and = (AndNode) vn;
left = and.getLeftOperand();
equals = (BinaryRelationalOperatorNode) left;
leftCol = equals.getLeftOperand();
rightCol = equals.getRightOperand();
if (logicalNPRefTableMap.get(((ColumnReference)leftCol).getTableNumber()) ||
logicalNPRefTableMap.get(((ColumnReference)rightCol).getTableNumber()))
{
push = false;
break;
}