private void EvaluateSingles(List <SqlBinaryExpression> list, List <ExpressionPlan> plans) { // The list of simple expression plans (lhs = single) var simplePlanList = new List <SingleColumnPlan>(); // The list of complex function expression plans (lhs = expression) var complexPlanList = new List <SingleColumnPlan>(); foreach (var expression in list) { // The single var ObjectName singleVar; SqlExpressionType op = expression.ExpressionType; SqlExpression left = expression.Left, right = expression.Right; if (expression.Right is SqlQuantifiedExpression) { singleVar = expression.Left.AsReferenceName(); if (singleVar != null) { plans.Add(new SimpleSelectPlan(this, singleVar, op, expression.Right)); } else { singleVar = expression.Left.DiscoverReferences().First(); plans.Add(new ComplexSinglePlan(this, singleVar, expression)); } } else { singleVar = expression.Left.DiscoverReferences().FirstOrDefault(); if (singleVar == null) { // Reverse the expressions and the operator var tempExp = left; left = right; right = tempExp; op = op.Reverse(); singleVar = left.DiscoverReferences().First(); } var tableSource = FindPlan(singleVar); // Simple LHS? var v = left.AsReferenceName(); if (v != null) { AddSingleColumnPlan(simplePlanList, tableSource, v, singleVar, new [] { left, right }, op); } else { // No, complex lhs AddSingleColumnPlan(complexPlanList, tableSource, null, singleVar, new [] { left, right }, op); } } } plans.AddRange(simplePlanList.Select(plan => new SimpleSinglePlan(this, plan.UniqueName, plan.Expression)).Cast <ExpressionPlan>()); plans.AddRange(complexPlanList.Select(plan => new ComplexSinglePlan(this, plan.UniqueName, plan.Expression)).Cast <ExpressionPlan>()); }
private static IQueryPlanNode PlanForOrderBy(IQueryPlanNode plan, IList <SortColumn> orderBy, QueryExpressionFrom queryFrom, IList <SelectColumn> selectedColumns) { // Sort on the ORDER BY clause if (orderBy.Count > 0) { int sz = orderBy.Count; var orderList = new ObjectName[sz]; var ascendingList = new bool[sz]; var functionOrders = new List <SqlExpression>(); for (int i = 0; i < sz; ++i) { var column = orderBy[i]; SqlExpression exp = column.Expression; ascendingList[i] = column.Ascending; var v = exp.AsReferenceName(); if (v != null) { var newV = queryFrom.ResolveReference(v); if (newV == null) { throw new InvalidOperationException(String.Format("Could not resolve ORDER BY column '{0}' in expression", v)); } newV = ReplaceAliasedVariable(newV, selectedColumns); orderList[i] = newV; } else { // Otherwise we must be ordering by an expression such as // '0 - a'. // Resolve the expression, exp = exp.Prepare(queryFrom.ExpressionPreparer); // Make sure we substitute any aliased columns in the order by // columns. exp = ReplaceAliasedVariables(exp, selectedColumns); // The new ordering functions are called 'FUNCTIONTABLE.#ORDER-n' // where n is the number of the ordering expression. orderList[i] = new ObjectName(FunctionTableName, "#ORDER-" + functionOrders.Count); functionOrders.Add(exp); } } // If there are functional orderings, // For this we must define a new FunctionTable with the expressions, // then order by those columns, and then use another SubsetNode // command node. int fsz = functionOrders.Count; if (fsz > 0) { var funs = new SqlExpression[fsz]; var fnames = new String[fsz]; for (int n = 0; n < fsz; ++n) { funs[n] = functionOrders[n]; fnames[n] = "#ORDER-" + n; } if (plan is SubsetNode) { // If the top plan is a SubsetNode then we use the // information from it to create a new SubsetNode that // doesn't include the functional orders we have attached here. var topSubsetNode = (SubsetNode)plan; var mappedNames = topSubsetNode.AliasColumnNames; // Defines the sort functions plan = new CreateFunctionsNode(plan, funs, fnames); // Then plan the sort plan = new SortNode(plan, orderList, ascendingList); // Then plan the subset plan = new SubsetNode(plan, mappedNames, mappedNames); } else { // Defines the sort functions plan = new CreateFunctionsNode(plan, funs, fnames); // Plan the sort plan = new SortNode(plan, orderList, ascendingList); } } else { // No functional orders so we only need to sort by the columns // defined. plan = new SortNode(plan, orderList, ascendingList); } } return(plan); }