public static IEnumerable <RewriteRule> AtomInvokeParam(SqlExprParams pars) { var invokeRule = RewriteRule.Create( "atomInvokeParam", () => RewriteSpecial.Call <RewriteTypes.C2>(null, "Invoke"), null, null, (match, expr, visit) => { var exprCall = (MethodCallExpression)expr; var origArgs = exprCall.Arguments; //Aplicar la transformación del from a los parametros, esto es importante porque el from //en algunos casos se usa sólo para especificar el tipo en un método generico pero su valor //no es importante. var fromArgs = origArgs .Select(x => Rewriter.RecApplyRules(x, ExprParamsRules(pars), ExcludeFromRewrite)) .ToList() ; var arg = fromArgs[0]; var args = fromArgs; var atomArg = Expression.Call(typeof(RewriteSpecial), "Atom", new[] { arg.Type }, arg); var atomArgs = new[] { atomArg }.Concat(args.Skip(1)).ToList(); var retCall = Expression.Call(exprCall.Object, exprCall.Method, atomArgs); return(retCall); }); return(new[] { invokeRule }); }
public void EvalBooleanRule() { //Evalua las expresiones booleanas, sólo se aplica la regla si la expresión no es ya una constante var evalBool = RewriteRule.Create("", (bool x) => RewriteSpecial.NotConstant(x), null, null, (_, x, visit) => ExprEval.EvalExprExpr(x)); var rules = new[] { evalBool }; var a = true; Expression <Func <bool, bool, bool> > expr = (x, y) => x && y || !(true || a); var red = ApplyRules(expr, rules); //Note que la expresión !(true || a) se evaluó por completo: Assert.AreEqual("(x, y) => ((x AndAlso y) OrElse False)", red.ToString()); }
public static IEnumerable <RewriteRule> ExprParamsRules(SqlExprParams pars) { var ret = new List <RewriteRule>(); //Puede ser null el param en caso de que todo sea por sustituciones del replace if (pars.Param != null) { //Es posible que el fromParam este envuelto en un Convert, por ejemplo cuando se usan propiedades de una interfaz ret.Add( RewriteRule.Create( "convertFromParam", (RewriteTypes.C1 p) => RewriteSpecial.Operator <RewriteTypes.C1, RewriteTypes.C2>(p, ExpressionType.Convert), (RewriteTypes.C1 p) => Sql.FromParam <RewriteTypes.C2>(), (match, expr) => match.Args[0] == pars.Param )); ret.Add( new RewriteRule( "fromParam", Expression.Lambda(pars.Param), Expression.Lambda(Expression.Call(typeof(Sql), nameof(Sql.FromParam), new[] { pars.Param.Type })), null, null) ); } return(ret); }
/// <summary> /// La regla que se aplica a las llamadas Atom(Raw(x)), lo que hace es convertir las llamadas ToSql del Atom(Raw(x)) /// </summary> public static IEnumerable <RewriteRule> AtomRawRule(SqlExprParams pars) { var deferredToSqlRule = RewriteRule.Create( "deferredToSql", (RewriteTypes.C1 x) => SqlFunctions.ToSql <RewriteTypes.C1>(x), null, null, (match, expr, visit) => Expression.Call( typeof(SqlExpression), nameof(SqlExpression.ExprToSql), new Type[0], Expression.Constant(match.Args[0]), Expression.Constant(pars), Expression.Constant(true))); var toSqlRule = RewriteRule.Create( "toSql", () => RewriteSpecial.Call <string>(typeof(SqlFunctions), nameof(ToSql)), null, null, (match, expr, visit) => Expression.Constant(SqlExpression.ExprToSql(((MethodCallExpression)expr).Arguments[0], pars, true))); var toSelectBodySqlRule = RewriteRule.Create( "toSelectBodySqlRule", () => RewriteSpecial.Call <string>(typeof(SqlFunctions), nameof(ToSelectBodySql)), null, null, (match, expr, visit) => Expression.Constant( SqlSelect.SelectExprToStr(SqlSelect.SelectBodyToStr(((MethodCallExpression)expr).Arguments[0], pars).Values) ) ); var windowToSqlRule = RewriteRule.Create( "windowToSql", (ISqlWindow a) => WindowToSql(a), null, null, (match, expr, visit) => Expression.Constant(SqlCalls.WindowToSql(match.Args[0])) ); var toSqlRules = new[] { toSelectBodySqlRule, toSqlRule, windowToSqlRule }; Func <Expression, Expression> applySqlRule = (Expression ex) => new RewriteVisitor(toSqlRules, ExcludeFromRewrite).Visit(ex); var atomRawRule = RewriteRule.Create( "executeAtomRaw", (string x) => RewriteSpecial.Atom(Sql.Raw <RewriteTypes.C1>(RewriteSpecial.NotConstant(x))), null, null, (match, expr, visit) => { var arg = match.Args[0]; var applySql = applySqlRule(arg); if (applySql == arg) { return(expr); } var type = match.Types[typeof(RewriteTypes.C1)]; var value = ExprEval.EvalExpr <string>(applySql).Value; var ret = Expression.Call(typeof(RewriteSpecial), nameof(RewriteSpecial.Atom), new[] { type }, Expression.Call(typeof(Sql), nameof(Sql.Raw), new[] { type }, Expression.Constant(value)) ); return(ret); }); return(new[] { atomRawRule }); }