/// <summary> /// Evaluates a list of expressions that are pattern searches (eg. LIKE, /// NOT LIKE and REGEXP). /// </summary> /// <param name="patternExprs"></param> /// <param name="evaluateOrder"></param> /// <remarks> /// The LHS or RHS may be complex expressions with variables, but we are /// guarenteed that there are no sub-expressions in the expression. /// </remarks> private void EvaluatePatterns(IEnumerable<Expression> patternExprs, IList<ExpressionPlan> evaluateOrder) { // Split the patterns into simple and complex plans. A complex plan // may require that a join occurs. foreach (Expression expr in patternExprs) { var binary = (BinaryExpression) expr; Expression[] exps = {binary.Left, binary.Right}; // If the LHS is a single variable and the RHS is a constant then // the conditions are right for a simple pattern search. ObjectName lhsVar = exps[0].AsVariable(); if (expr.IsConstant()) { ExpressionPlan exprPlan = new ConstantExpressionPlan(this, expr); exprPlan.OptimizableValue = 0f; evaluateOrder.Add(exprPlan); } else if (lhsVar != null && exps[1].IsConstant()) { ExpressionPlan exprPlan = new SimplePatternExpressionPlan(this, lhsVar, expr); exprPlan.OptimizableValue = 0.25f; evaluateOrder.Add(exprPlan); } else { // Otherwise we must assume a complex pattern search which may // require a join. For example, 'a + b LIKE 'a%'' or // 'a LIKE b'. At the very least, this will be an exhaustive // search and at the worst it will be a join + exhaustive search. // So we should evaluate these at the end of the evaluation order. ExpressionPlan exprPlan = new ExhaustiveSelectExpressionPlan(this, expr); exprPlan.OptimizableValue = 0.82f; evaluateOrder.Add(exprPlan); } } }
/// <summary> /// Evaluates a list of expressions containing sub-queries. /// </summary> /// <param name="expressions"></param> /// <param name="evaluateOrder"></param> /// <remarks> /// Non-correlated sub-queries can often be optimized in to fast /// searches. Correlated queries, or expressions containing multiple /// sub-queries are write through the <see cref="ExhaustiveSelectExpressionPlan"/>. /// </remarks> private void EvaluateSubQueries(IEnumerable<Expression> expressions, IList<ExpressionPlan> evaluateOrder) { // For each sub-command expression foreach (Expression andexp in expressions) { var binary = (BinaryExpression) andexp; bool isExhaustive; // Is this an easy sub-command? Operator op = binary.Operator; if (!op.IsSubQuery()) { // Must be an exhaustive sub-command isExhaustive = true; } else { // Split the expression. Expression[] exps ={binary.Left, binary.Right}; // Check that the left is a simple enough variable reference ObjectName leftVar = exps[0].AsVariable(); if (leftVar == null) isExhaustive = true; else { // Check that the right is a sub-command plan. IQueryPlanNode rightPlan = exps[1].AsQueryPlanNode(); if (rightPlan == null) isExhaustive = true; else { // Finally, check if the plan is correlated or not IList<CorrelatedVariable> cv = rightPlan.DiscoverCorrelatedVariables(1, new List<CorrelatedVariable>()); isExhaustive = cv.Count != 0; } } } // If this is an exhaustive operation, if (isExhaustive) { // This expression could involve multiple variables, so we may need // to join. IList<ObjectName> allVars = andexp.AllVariables().ToList(); // Also find all correlated variables. int level = 0; IList<CorrelatedVariable> allCorrelated = andexp.DiscoverCorrelatedVariables(ref level, new List<CorrelatedVariable>()); 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 (allVars.Count == 0 && sz == 0) { ExpressionPlan exprPlan = new ConstantExpressionPlan(this, andexp); exprPlan.OptimizableValue = 0f; evaluateOrder.Add(exprPlan); } else { foreach (CorrelatedVariable cv in allCorrelated) allVars.Add(cv.Variable); // An exhaustive expression plan which might require a join or a // slow correlated search. This should be evaluated after the // multiple variables are processed. ExpressionPlan expPlan = new ExhaustiveSubQueryExpressionPlan(this, allVars, andexp); expPlan.OptimizableValue = 0.85f; evaluateOrder.Add(expPlan); } } else { // This is a simple sub-command expression plan with a single LHS // variable and a single RHS sub-command. ExpressionPlan expPlan = new SimpleSubQueryExpressionPlan(this, andexp); expPlan.OptimizableValue = 0.3f; evaluateOrder.Add(expPlan); } } // For each 'and' expression }
// ---- // An expression plan for a constant expression. These are very // optimizable indeed. /// <summary> /// Evaluates a list of constant conditional exressions of /// the form <c>3 + 2 = 0</c>, <c>true = true</c>, etc. /// </summary> /// <param name="constantVars"></param> /// <param name="evaluateOrder"></param> private void EvaluateConstants(IEnumerable<Expression> constantVars, IList<ExpressionPlan> evaluateOrder) { // For each constant variable foreach (Expression expr in constantVars) { // Add the exression plan ExpressionPlan expPlan = new ConstantExpressionPlan(this, expr); expPlan.OptimizableValue = 0f; evaluateOrder.Add(expPlan); } }