private void EvaluateSubQueries(List<SqlBinaryExpression> list, List<ExpressionPlan> plans)
{
foreach (var expression in list) {
bool exhaustive;
var op = expression.ExpressionType;
if (expression.Right is SqlQuantifiedExpression) {
// Must be an exhaustive sub-command
exhaustive = true;
} else {
// Check that the left is a simple enough variable reference
var leftColumn = expression.Left.AsReferenceName();
if (leftColumn == null) {
exhaustive = true;
} else {
// Check that the right is a sub-command plan.
IQueryPlanNode rightPlan = expression.Right.AsQueryPlan();
if (rightPlan == null)
exhaustive = true;
else {
// Finally, check if the plan is correlated or not
var cv = rightPlan.DiscoverQueryReferences(1);
exhaustive = cv.Count != 0;
}
}
}
if (exhaustive) {
// This expression could involve multiple variables, so we may need
// to join.
var columnNames = expression.DiscoverReferences().ToList();
// Also find all correlated variables.
int level = 0;
var allCorrelated = expression.DiscoverQueryReferences(ref level);
int sz = allCorrelated.Count;
// If there are no variables (and no correlated variables) then this
// must be a constant select, For example, 3 in ( select ... )
if (!columnNames.Any() && sz == 0) {
plans.Add(new ConstantPlan(this, expression));
} else {
columnNames.AddRange(allCorrelated.Select(cv => cv.Name));
// An exhaustive expression plan which might require a join or a
// slow correlated search. This should be evaluated after the
// multiple variables are processed.
plans.Add(new ExhaustiveSubQueryPlan(this, columnNames.ToArray(), expression));
}
} else {
plans.Add(new SimpleSubQueryPlan(this, expression));
}
}
}