private Expression SimplifyTerm(Expression expression) { if (expression is FunctionExpression) { FunctionExpression functionExp = (FunctionExpression) expression; // Get the function name string functionName = functionExp.Name; // If the function is an object comparator, if (IsSimpleComparison(functionName)) { // First try and simplify, Expression p1 = SimplifyTerm((Expression) functionExp.Parameters[0]); Expression p2 = SimplifyTerm((Expression) functionExp.Parameters[1]); // Is one of the terms is a fetchvar and the other is static, then // we can make a selectable range set function. Variable v1 = AsVariable(p1); Variable v2 = AsVariable(p2); SqlObject[] r1 = EvaluateExpression(p1); SqlObject[] r2 = EvaluateExpression(p2); Variable v; SqlObject[] ob; string rangeOp; if (v1 != null && r2 != null) { v = v1; ob = r2; rangeOp = functionName; } else if (v2 != null && r1 != null) { // We need to reverse the operator in this case v = v2; ob = r1; rangeOp = ReverseSimpleComparison(functionName); } else { // if both are static, evaluate and return the operation FunctionExpression new_fun = new FunctionExpression(functionName, new Expression[] { p1, p2 }); if (r1 != null && r2 != null) return new FetchStaticExpression(EvaluateExpression(new_fun)); // Can't simplify return new_fun; } // Make the range set, SelectableRange rangeSet = SelectableRange.Full; rangeSet = rangeSet.Intersect(SelectableRange.GetOperatorFromFunction(rangeOp), ob); FunctionExpression funExp = new FunctionExpression("range_set"); funExp.Parameters.Add(new FetchVariableExpression(v)); funExp.Parameters.Add(rangeSet); funExp.SetArgument("full_range_object", ob); return funExp; } if (IsSimpleLogical(functionName)) { // either and/or // If it's a logical operation Expression p1 = SimplifyTerm((Expression) functionExp.Parameters[0]); Expression p2 = SimplifyTerm((Expression) functionExp.Parameters[1]); // Can we combine the terms? Variable v1 = GetSingleVariable(p1); Variable v2 = GetSingleVariable(p2); // If one of the terms is a range set bool success; Expression otherTerm = null; if (v1 != null) { Variable v = v1; FunctionExpression rangeSetTerm = (FunctionExpression) p1; otherTerm = p2; success = AttemptRangeSetMerge(v, rangeSetTerm, otherTerm, functionName); } else if (v2 != null) { Variable v = v2; FunctionExpression rangeSetTerm = (FunctionExpression) p2; otherTerm = p1; success = AttemptRangeSetMerge(v, rangeSetTerm, otherTerm, functionName); } else { // Neither left or right is a 'range_set' success = false; } // Try and merge the range set term with the other term // If it was a success, then we return the other term, if (success) return otherTerm; // Otherwise, look for a static term, // If one of the terms is a static, SqlObject[] r1 = EvaluateExpression(p1); SqlObject[] r2 = EvaluateExpression(p2); SqlObject[] staticVal = null; Expression nonStaticVal = null; if (r1 != null && r2 != null) { // Both are static, so evaluate and return FunctionExpression newFun = new FunctionExpression(functionName, new Expression[] {p1, p2}); return new FetchStaticExpression(EvaluateExpression(newFun)); } if (r1 != null) { staticVal = r1; nonStaticVal = p2; } else if (r2 != null) { staticVal = r2; nonStaticVal = p1; } // If one of the sides is static, if (staticVal != null) { // If it's a single value, if (staticVal.Length == 1) { SqlObject tv = staticVal[0]; if (tv.Type.IsBoolean) { bool? valb = tv.Value.ToBoolean(); if (valb != null) { // If it's true if (valb == true) return functionName.Equals("or") ? new FetchStaticExpression(staticVal) : nonStaticVal; // If it's false if (valb == false) return functionName.Equals("or") ? nonStaticVal : new FetchStaticExpression(staticVal); } } } else { // If it's not true of false return functionName.Equals("or") ? nonStaticVal : new FetchStaticExpression(SqlObject.MakeNull(SqlType.GetSqlType(typeof(bool)))); } } // Ok, neither side static, // If one of the sides is a range_set, then we search the other side // of the tree for a potential term to merge with. return new FunctionExpression(functionName, new Expression[] {p1, p2}); } // Perhaps we can simplify a static operation? // Simplify the terms of the functions arguments, int sz = functionExp.Parameters.Count; object[] newParams = new object[sz]; bool allStaticParams = true; for (int i = 0; i < sz; ++i) { object ob = functionExp.Parameters[i]; if (ob != null && ob is Expression) { Expression paramExp = (Expression)ob; paramExp = SimplifyTerm(paramExp); newParams[i] = paramExp; if (!(paramExp is FetchStaticExpression)) allStaticParams = false; } else { newParams[i] = ob; } } // If the function graph is static, evaluate it and return the fetch // static operation FunctionExpression funcExp = new FunctionExpression(functionName); for (int i = 0; i < sz; ++i) { funcExp.Parameters.Add(newParams[i]); } if (allStaticParams && IsSimpleEvaluable(functionName)) { return new FetchStaticExpression(EvaluateExpression(funcExp)); } return funcExp; } return expression; }