LinkedList<PlanNode> targets = determineTargets(dependentNode,
metadata, capFinder, rpsc, depExpr, depExpressions);
Iterator<Expression> exprIter = depExpressions.iterator();
for (Iterator<PlanNode> targetIter = targets.iterator(); targetIter.hasNext();) {
PlanNode target = targetIter.next();
Expression targerDepExpr = exprIter.next();
PlanNode accessNode = NodeEditor.findParent(target, NodeConstants.Types.ACCESS);
float setCriteriaBatchSize = indSymbolNDV;
if (accessNode != null) {
setCriteriaBatchSize = CapabilitiesUtil.getMaxInCriteriaSize(RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder);
if (setCriteriaBatchSize < 1) {
setCriteriaBatchSize = indSymbolNDV;
} else {
int numberOfSets = CapabilitiesUtil.getMaxDependentPredicates(RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder);
if (numberOfSets > 0) {
setCriteriaBatchSize *= Math.max(1, numberOfSets /dependentExpressions.size()); //scale down to be conservative
}
}
} else if (indSymbolNDV > processorBatchSize) {
//don't bother making a virtual join dependent if they are likely to be large
//TODO: what operations are performed between origNode and dependentNode
//TODO: we should be using a tree structure rather than just a value iterator
continue;
}
if (target.hasBooleanProperty(Info.MAKE_NOT_DEP)) {
continue;
}
Collection<ElementSymbol> depElems = ElementCollectorVisitor.getElements(targerDepExpr, true);
while (target.getParent().getType() == NodeConstants.Types.SELECT) {
target = target.getParent();
}
float depTargetCardinality = computeCostForTree(target, metadata);
if (depTargetCardinality == UNKNOWN_VALUE) {
continue;
}
float depSymbolNDV = getStat(Stat.NDV, depElems, target, depTargetCardinality, metadata);
boolean usesKey = usesKey(dependentNode, depElems, metadata);
if (depSymbolNDV == UNKNOWN_VALUE) {
if (!usesKey) {
//make an educated guess that this is a fk
float indSymbolOrigNDV = indSymbolNDV;
float indCardinalityOrig = independentCardinality;
//TODO: we should probably dig deeper than this
PlanNode indOrigNode = FrameUtil.findOriginatingNode(independentNode, GroupsUsedByElementsVisitor.getGroups(indElements));
if (indOrigNode != null) {
indCardinalityOrig = computeCostForTree(indOrigNode, metadata);
indSymbolOrigNDV = getStat(Stat.NDV, indElements, indOrigNode, indCardinalityOrig, metadata);
if (indSymbolOrigNDV == UNKNOWN_VALUE) {
indSymbolOrigNDV = indCardinalityOrig * indSymbolNDV / independentCardinality;