* The caller can raise an alarm if there is more than one.
*/
public void analyzeForMultiPartitionAccess(Collection<StmtTableScan> collection,
HashMap<AbstractExpression, Set<AbstractExpression>> valueEquivalence)
{
TupleValueExpression tokenPartitionKey = null;
Set< Set<AbstractExpression> > eqSets = new HashSet< Set<AbstractExpression> >();
int unfilteredPartitionKeyCount = 0;
// reset this flag to forget the last result of the multiple partition access path.
// AdHoc with parameters will call this function at least two times
// By default this flag should be true.
m_joinValid = true;
boolean subqueryHasReceiveNode = false;
boolean hasPartitionedTableJoin = false;
// Iterate over the tables to collect partition columns.
for (StmtTableScan tableScan : collection) {
// Replicated tables don't need filter coverage.
if (tableScan.getIsReplicated()) {
continue;
}
// The partition column can be null in an obscure edge case.
// The table is declared non-replicated yet specifies no partitioning column.
// This can occur legitimately when views based on partitioned tables neglect to group by the partition column.
// The interpretation of this edge case is that the table has "randomly distributed data".
// In such a case, the table is valid for use by MP queries only and can only be joined with replicated tables
// because it has no recognized partitioning join key.
List<SchemaColumn> columnsNeedingCoverage = tableScan.getPartitioningColumns();
if (tableScan instanceof StmtSubqueryScan) {
StmtSubqueryScan subScan = (StmtSubqueryScan) tableScan;
subScan.promoteSinglePartitionInfo(valueEquivalence, eqSets);
if (subScan.hasReceiveNode()) {
if (subqueryHasReceiveNode) {
// Has found another subquery with receive node on the same level
// Not going to support this kind of subquery join with 2 fragment plan.
m_joinValid = false;
// Still needs to count the independent partition tables
break;
}
subqueryHasReceiveNode = true;
if (subScan.isTableAggregate()) {
// Partition Table Aggregate only return one aggregate row.
// It has been marked with receive node, any join or processing based on
// this table aggregate subquery should be done on coordinator.
// Joins: has to be replicated table
// Any process based on this subquery should require 1 fragment only.
continue;
}
} else {
// this subquery partition table without receive node
hasPartitionedTableJoin = true;
}
} else {
// This table is a partition table
hasPartitionedTableJoin = true;
}
boolean unfiltered = true;
for (AbstractExpression candidateColumn : valueEquivalence.keySet()) {
if ( ! (candidateColumn instanceof TupleValueExpression)) {
continue;
}
TupleValueExpression candidatePartitionKey = (TupleValueExpression) candidateColumn;
if (! canCoverPartitioningColumn(candidatePartitionKey, columnsNeedingCoverage)) {
continue;
}
unfiltered = false;
if (tokenPartitionKey == null) {