internal static Expression Bind(DataAccessModel dataAccessModel, SqlDataTypeProvider sqlDataTypeProvider, Expression expression) { var placeholderCount = -1; expression = Evaluator.PartialEval(expression, ref placeholderCount); expression = QueryBinder.Bind(dataAccessModel, expression); expression = SqlEnumTypeNormalizer.Normalize(expression, sqlDataTypeProvider.GetTypeForEnums()); expression = Evaluator.PartialEval(expression, ref placeholderCount); expression = SqlNullComparisonCoalescer.Coalesce(expression); expression = SqlTupleOrAnonymousTypeComparisonExpander.Expand(expression); expression = SqlObjectOperandComparisonExpander.Expand(expression); expression = SqlRedundantFunctionCallRemover.Remove(expression); return(expression); }
public static Expression Optimize(Expression expression, Type typeForEnums, bool simplerPartialVal = true) { expression = SqlObjectOperandComparisonExpander.Expand(expression); expression = SqlEnumTypeNormalizer.Normalize(expression, typeForEnums); expression = SqlGroupByCollator.Collate(expression); expression = SqlAggregateSubqueryRewriter.Rewrite(expression); expression = SqlUnusedColumnRemover.Remove(expression); expression = SqlRedundantColumnRemover.Remove(expression); expression = SqlRedundantSubqueryRemover.Remove(expression); expression = SqlFunctionCoalescer.Coalesce(expression); expression = SqlExistsSubqueryOptimizer.Optimize(expression); expression = SqlRedundantBinaryExpressionsRemover.Remove(expression); expression = SqlCrossJoinRewriter.Rewrite(expression); if (simplerPartialVal) { expression = Evaluator.PartialEval(expression, c => c.NodeType != (ExpressionType)SqlExpressionType.ConstantPlaceholder && Evaluator.CanBeEvaluatedLocally(c)); } else { expression = Evaluator.PartialEval(expression); } expression = SqlRedundantFunctionCallRemover.Remove(expression); expression = SqlConditionalEliminator.Eliminate(expression); expression = SqlExpressionCollectionOperationsExpander.Expand(expression); expression = SqlSumAggregatesDefaultValueCoalescer.Coalesce(expression); expression = SqlOrderByRewriter.Rewrite(expression); var rewritten = SqlCrossApplyRewriter.Rewrite(expression); if (rewritten != expression) { expression = rewritten; expression = SqlUnusedColumnRemover.Remove(expression); expression = SqlRedundantColumnRemover.Remove(expression); expression = SqlRedundantSubqueryRemover.Remove(expression); expression = SqlOrderByRewriter.Rewrite(expression); } return(expression); }
protected virtual FunctionResolveResult ResolveSqlFunction(SqlFunctionCallExpression functionExpression) { var function = functionExpression.Function; var arguments = functionExpression.Arguments; switch (function) { case SqlFunction.IsNull: return(new FunctionResolveResult("", true, arguments) { functionSuffix = " IS NULL" }); case SqlFunction.IsNotNull: return(new FunctionResolveResult("", true, arguments) { functionSuffix = " IS NOT NULL" }); case SqlFunction.In: return(new FunctionResolveResult("IN", true, arguments)); case SqlFunction.Exists: return(new FunctionResolveResult("EXISTSOPERATOR", true, arguments) { functionPrefix = " EXISTS " }); case SqlFunction.UserDefined: return(new FunctionResolveResult(functionExpression.UserDefinedFunctionName, false, arguments)); case SqlFunction.Coalesce: return(new FunctionResolveResult("COALESCE", false, arguments)); case SqlFunction.Like: return(new FunctionResolveResult(this.sqlDialect.GetSyntaxSymbolString(SqlSyntaxSymbol.Like), true, arguments)); case SqlFunction.CompareObject: var expressionType = (ExpressionType)((ConstantExpression)arguments[0]).Value; var args = new Expression[2]; args[0] = arguments[1]; args[1] = arguments[2]; switch (expressionType) { case ExpressionType.LessThan: return(new FunctionResolveResult("<", true, args.ToReadOnlyList())); case ExpressionType.LessThanOrEqual: return(new FunctionResolveResult("<=", true, args.ToReadOnlyList())); case ExpressionType.GreaterThan: return(new FunctionResolveResult(">", true, args.ToReadOnlyList())); case ExpressionType.GreaterThanOrEqual: return(new FunctionResolveResult(">=", true, args.ToReadOnlyList())); } throw new InvalidOperationException(); case SqlFunction.NotLike: return(new FunctionResolveResult("NOT " + this.sqlDialect.GetSyntaxSymbolString(SqlSyntaxSymbol.Like), true, arguments)); case SqlFunction.ServerNow: return(new FunctionResolveResult("NOW", false, arguments)); case SqlFunction.ServerUtcNow: return(new FunctionResolveResult("UTCNOW", false, arguments)); case SqlFunction.StartsWith: { Expression newArgument = new SqlFunctionCallExpression(typeof(string), SqlFunction.Concat, arguments[1], Expression.Constant("%")); newArgument = SqlRedundantFunctionCallRemover.Remove(newArgument); var list = new List <Expression> { arguments[0], newArgument }; return(new FunctionResolveResult(this.sqlDialect.GetSyntaxSymbolString(SqlSyntaxSymbol.Like), true, list.ToReadOnlyList())); } case SqlFunction.ContainsString: { Expression newArgument = new SqlFunctionCallExpression(typeof(string), SqlFunction.Concat, arguments[1], Expression.Constant("%")); newArgument = new SqlFunctionCallExpression(typeof(string), SqlFunction.Concat, Expression.Constant("%"), newArgument); newArgument = SqlRedundantFunctionCallRemover.Remove(newArgument); var list = new List <Expression> { arguments[0], newArgument }; return(new FunctionResolveResult(this.sqlDialect.GetSyntaxSymbolString(SqlSyntaxSymbol.Like), true, list.ToReadOnlyList())); } case SqlFunction.EndsWith: { Expression newArgument = new SqlFunctionCallExpression(typeof(string), SqlFunction.Concat, Expression.Constant("%"), arguments[1]); newArgument = SqlRedundantFunctionCallRemover.Remove(newArgument); var list = new List <Expression> { arguments[0], newArgument }; return(new FunctionResolveResult(this.sqlDialect.GetSyntaxSymbolString(SqlSyntaxSymbol.Like), true, list.ToReadOnlyList())); } default: return(new FunctionResolveResult(function.ToString().ToUpper(), false, arguments)); } }