示例#1
0
        public void ToSqlRuleContains()
        {
            var nombres = new[] { "rafa", "hola" };
            Expression <Func <Cliente, string[]> > selectBody = x => Sql.Record(nombres);

            var pars = new SqlExprParams(selectBody.Parameters[0], null, false, "cli", new SqlFromList.ExprStrRawSql[0], ParamMode.None, new SqlParamDic());

            var rules =
                SqlFunctions.AtomRawRule(pars)
                .Concat(
                    SqlFunctions.ExprParamsRules(pars)
                    )
                .Concat(new[] {
                DefaultRewrite.StringFormat
            })
                .Concat(SqlFunctions.stringCalls)
                .Concat(SqlFunctions.sqlCalls)
                .Concat(SqlFunctions.rawAtom)
                .ToList();

            var ret     = ApplyRules(selectBody, rules);
            var rawBody = ((MethodCallExpression)((LambdaExpression)ret).Body).Arguments[0];

            ExprEval.TryEvalExpr <string>(rawBody, out var rawStr);
            var expected = "('rafa', 'hola')";

            Assert.AreEqual(expected, rawStr);
        }
示例#2
0
        public void ToSqlRuleContainsifCond()
        {
            string[] nombres = null;


            Expression <Func <Cliente, bool> > selectBody = x => SqlExpr.IfCond.Invoke(nombres.Any(), nombres.Contains(x.Nombre));
            var pars = new SqlExprParams(selectBody.Parameters[0], null, false, "cli", new SqlFromList.ExprStrRawSql[0], ParamMode.None, new SqlParamDic());

            var visitor = new SqlRewriteVisitor(pars);

            {
                nombres = new[] { "rafa", "hola" };
                var ret     = visitor.Visit(selectBody);
                var rawBody = ((MethodCallExpression)((LambdaExpression)ret).Body).Arguments[0];
                ExprEval.TryEvalExpr <string>(rawBody, out var rawStr);
                var expected = "(\"cli\".\"Nombre\" IN ('rafa', 'hola'))";
                Assert.AreEqual(expected, rawStr);
            }

            {
                nombres = new string[0];

                var ret     = visitor.Visit(selectBody);
                var rawBody = ((MethodCallExpression)((LambdaExpression)ret).Body).Arguments[0];
                ExprEval.TryEvalExpr <string>(rawBody, out var rawStr);
                var expected = "True";
                Assert.AreEqual(expected, rawStr);
            }
        }
示例#3
0
        /// <summary>
        ///
        /// </summary>
        static string OnConflictDoUpdate(OnConflictDoUpdateClause doUpdate, ParamMode paramMode, SqlParamDic paramDic, string origTableName)
        {
            var b = new StringBuilder();

            b.AppendLine("DO UPDATE");
            b.AppendLine("SET");
            var exprAlias = new[]
            {
                new SqlFromList.ExprStrRawSql(doUpdate.Set.Parameters[0], "EXCLUDED"),
                new SqlFromList.ExprStrRawSql(doUpdate.Set.Parameters[1], $"\"{origTableName}\""),
            };
            var setSql = SqlUpdate.SetToSql(doUpdate.Set.Body, paramMode, paramDic, exprAlias);

            b.Append(SqlSelect.TabStr(setSql));

            if (doUpdate.Where != null)
            {
                b.AppendLine();

                var pars     = new SqlExprParams(null, null, false, "", new SqlFromList.ExprStrRawSql[0], paramMode, paramDic);
                var whereSql = SqlExpression.ExprToSql(doUpdate.Where.Body, pars, true);
                b.Append(whereSql);
            }

            return(b.ToString());
        }
示例#4
0
        public void ToSqlRule3()
        {
            Expression <Func <Cliente, bool> > selectBody = x => x.Nombre.Contains("Hola");

            var pars = new SqlExprParams(selectBody.Parameters[0], null, false, "cli", new SqlFromList.ExprStrRawSql[0], ParamMode.None, new SqlParamDic());

            var rules =
                SqlFunctions.rawAtom.Concat(
                    SqlFunctions.ExprParamsRules(pars)
                    )
                .Concat(new[] {
                DefaultRewrite.StringFormat
            })
                .Concat(SqlFunctions.stringCalls)
                .Concat(SqlFunctions.AtomRawRule(pars))
                .ToList();

            var ret     = ApplyRules(selectBody, rules);
            var rawBody = ((MethodCallExpression)((LambdaExpression)ret).Body).Arguments[0];

            ExprEval.TryEvalExpr <string>(rawBody, out var rawStr);
            var expected = "(\"cli\".\"Nombre\" LIKE '%' || 'Hola' || '%')";

            Assert.AreEqual(expected, rawStr);
        }
示例#5
0
        public void MultipleIfCond()
        {
            var filtro = new Uruz.FiltroFacturas
            {
                FechaInicio = new DateTime(2019, 01, 26)
            };

            Expression <Func <Uruz.FacturaDTO, bool> > expr = x =>
                                                              SqlExpr.IfCond.Invoke(filtro.FechaInicio != null, x.FechaCreacion >= filtro.FechaInicio) &&
                                                              SqlExpr.IfCond.Invoke(filtro.FechaFinal != null, x.FechaCreacion <= filtro.FechaFinal) &&
                                                              SqlExpr.IfCond.Invoke(filtro.FechaPagoInicio != null, x.FechaPago >= filtro.FechaPagoInicio) &&
                                                              SqlExpr.IfCond.Invoke(filtro.FechaPagoFinal != null, x.FechaPago <= filtro.FechaPagoFinal)
            ;

            var pars = new SqlExprParams(expr.Parameters[0], null, false, "fac", new SqlFromList.ExprStrRawSql[0], ParamMode.EntityFramework, new SqlParamDic());

            var visitor = new SqlRewriteVisitor(pars);
            var ret     = visitor.Visit(expr);
            var apps    = RewriteVisitor.applications;

            var expected = "x => Raw(\"(\"fac\".\"FechaCreacion\" >= @FechaInicio)\")";
            var actual   = ret.ToString();

            Assert.AreEqual(expected, actual);
        }
示例#6
0
        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 });
        }
示例#7
0
        /// <summary>
        /// Convierte la cláusula RETURNING a SQL
        /// </summary>
        static (string sql, IReadOnlyList <string> cols) ReturningToString(LambdaExpression returning, ParamMode paramMode, SqlParamDic paramDic, string tableName)
        {
            var pars   = new SqlExprParams(returning.Parameters[0], null, false, tableName, new SqlFromList.ExprStrRawSql[0], paramMode, paramDic);
            var select = SqlSelect.SelectBodyToStr(returning.Body, pars);
            var sql    = $"RETURNING {Environment.NewLine}{SqlSelect.TabStr(SqlSelect.SelectExprToStr(select.Values))}";
            var cols   = select.Values.Select(x => x.Column).ToList();

            return(sql, cols);
        }
示例#8
0
        static void ConvertWhere(StringBuilder b, DeleteClause clause, ParamMode paramMode, SqlParamDic paramDic)
        {
            var whereParms = clause.Where.Parameters;
            var tableParam = whereParms[0];
            var usingParam = whereParms[1];

            var replace = new SqlFromList.ExprStrRawSql[0];
            var pars    = new SqlExprParams(tableParam, null, false, null, replace, paramMode, paramDic);

            var whereSql = SqlExpression.ExprToSql(clause.Where.Body, pars, true);

            b.Append("WHERE ");
            b.Append(whereSql);
        }
示例#9
0
        public SqlRewriteVisitor(SqlExprParams pars)
        {
            var exprParamRules = SqlFunctions.ExprParamsRules(pars);

            //The order of the rule passes is important to the performance and correctness!

            rules = new List <IEnumerable <RewriteRule> >();
            //Primero quita los invokes
            rules.Add(
                new[]
            {
                DefaultRewrite.InvokeRule(exprParamRules)
            });

            rules.Add(DefaultRewrite.BooleanSimplify);

            rules.Add(
                exprParamRules
                );

            rules.Add(
                SqlFunctions.rawAtom
                .Concat(SqlFunctions.AtomInvokeParam(pars))
                .Concat(
                    new[]
            {
                SqlConst.constToSqlRule,
                DefaultRewrite.StringFormat,
                SqlFunctions.rawCallRule
            }
                    )
                .Concat(SqlOperators.eqNullRule)
                .Concat(SqlOperators.nullableRules)
                .Concat(SqlOperators.unaryRules)
                .Concat(SqlOperators.binaryRules)
                .Concat(SqlStar.starRules)
                .Concat(SqlOperators.compareTo)
                .Concat(SqlFunctions.stringCalls)
                .Concat(SqlFunctions.subqueryExprs)
                .Concat(SqlFunctions.sqlCalls)
                .Concat(SqlFunctions.AtomRawRule(pars))
                .ToList()
                )
            ;
        }
示例#10
0
        public void ToSqlStringConcat()
        {
            Expression <Func <Uruz.Factura, string> > nombreFactura = x => x.Serie + "-" + x.Folio;
            Expression <Func <Uruz.Factura, string> > selectBody    = x => nombreFactura.Invoke(x);

            var pars = new SqlExprParams(selectBody.Parameters[0], null, false, "cli", new SqlFromList.ExprStrRawSql[0], ParamMode.None, new SqlParamDic());



            var visitor = new SqlRewriteVisitor(pars);
            var ret     = visitor.Visit(selectBody);
            var rawBody = ((MethodCallExpression)((LambdaExpression)ret).Body).Arguments[0];

            ExprEval.TryEvalExpr <string>(rawBody, out var rawStr);
            var expected = @"((""cli"".""Serie"" || '-') || ""cli"".""Folio"")";

            Assert.AreEqual(expected, rawStr);
        }
示例#11
0
        public void ToSqlRuleContainsEmpty()
        {
            var nombres = new string[0];

            Expression <Func <Cliente, bool> > selectBody = x => nombres.Contains(x.Nombre);
            var pars = new SqlExprParams(selectBody.Parameters[0], null, false, "cli", new SqlFromList.ExprStrRawSql[0], ParamMode.None, new SqlParamDic());

            var visitor = new SqlRewriteVisitor(pars);

            {
                nombres = new string[0];

                var ret     = visitor.Visit(selectBody);
                var rawBody = ((MethodCallExpression)((LambdaExpression)ret).Body).Arguments[0];
                ExprEval.TryEvalExpr <string>(rawBody, out var rawStr);
                var expected = "False";
                Assert.AreEqual(expected, rawStr);
            }
        }
示例#12
0
        /// <summary>
        /// Convierte a string la parte del VALUE de un INSERT
        /// </summary>
        static string InsertValueToString(InsertClause clause, ParamMode paramMode, SqlParamDic paramDic)
        {
            var b = new StringBuilder();
            //Note que aquí el fromAlias no afecta ya se se usan directamente los nombres de las columnas
            //y no se puede referenciar a la tabla de origen en los VALUES
            var pars = new SqlExprParams(null, null, false, null, new SqlFromList.ExprStrRawSql[0], paramMode, paramDic);

            //Hacer el rewrite en todo el body:
            var visitor = new SqlRewriteVisitor(pars);
            var body    = visitor.Visit(clause.Value);

            var exprs = SqlSelect
                        .ExtractInitExpr(body)
                        .Select(x => (x.mem, sql: SqlExpression.ExprToSqlStar(x.expr, pars, false)))
            ;

            if (exprs.Any(y => y.sql.star))
            {
                throw new ArgumentException("No esta soportado una expresión star '*' en la asignación de los valores de un INSERT");
            }

            var subpaths = exprs.SelectMany(x => x.sql.sql, (parent, child) => (member: parent.mem, subpath: child));
            //Nombres de las columnas del INSERT
            var columns = subpaths
                          .Select(x => SqlSelect.MemberToColumnName(x.member, x.subpath))
                          .Select(SqlSelect.ColNameToStr);

            ;
            //Valores:
            var values = subpaths.Select(x => x.subpath.Sql);

            //Texto de las columnas:
            b.Append("(");
            b.Append(string.Join(", ", columns));
            b.AppendLine(")");

            //Texto de los vaues:
            b.Append("VALUES (");
            b.Append(string.Join(", ", values));
            b.Append(")");

            return(b.ToString());
        }
示例#13
0
        public void CompareToTest()
        {
            Expression <Func <Cliente, bool> > select = (cli) => cli.Nombre.CompareTo(cli.Apellido) >= 0;
            var pars = new SqlExprParams(select.Parameters[0], null, false, "cli", new SqlFromList.ExprStrRawSql[0], ParamMode.None, new SqlParamDic());


            var rules = SqlFunctions.rawAtom.Concat(
                SqlOperators.compareTo
                )
                        .Concat(
                SqlFunctions.AtomRawRule(pars)
                )
            ;

            var ret      = (LambdaExpression)ApplyRules(select, rules);
            var raw      = ExprEval.EvalExpr <string>(((MethodCallExpression)ret.Body).Arguments[0]).Value;
            var expected = "(\"cli\".\"Nombre\" >= \"cli\".\"Apellido\")";

            Assert.AreEqual(expected, raw);
        }
示例#14
0
        /// <summary>
        /// Convierte la cláusura ON CONFLICT
        /// </summary>
        static string OnConflict(OnConflictClause onConf, ParamMode paramMode, SqlParamDic paramDic, string tableName)
        {
            var b = new StringBuilder();
            //fromAlias es null ya que en la expresion de indice de ON CONFLICT no se permiten
            //los identificadores de las tablas, sólo se permiten los nombres tal cual de las columnas
            var pars      = new SqlExprParams(null, null, false, null, new SqlFromList.ExprStrRawSql[0], paramMode, paramDic);
            var indexExpr = onConf
                            .IndexExpressions
                            .Select(x => SqlExpression.ExprToSql(x.Body, pars.ReplaceSelectParams(x.Parameters[0], null), true))
            ;

            b.Append("ON CONFLICT ");
            if (indexExpr.Any())
            {
                b.Append("(");
                b.Append(string.Join(", ", indexExpr));
                b.Append(") ");
            }

            if (onConf.Where != null)
            {
                var whereSql = SqlExpression.ExprToSql(onConf.Where.Body, pars.ReplaceSelectParams(onConf.Where.Parameters[0], null), true);
                b.Append("WHERE ");
                b.Append(whereSql);
            }

            if (onConf.DoUpdate == null)
            {
                //Si DoUpdate es null se considera que es DO NOTHING
                b.Append("DO NOTHING");
            }
            else
            {
                b.Append(OnConflictDoUpdate(onConf.DoUpdate, paramMode, paramDic, tableName));
            }

            return(b.ToString());
        }
示例#15
0
        public void MultipleIfCond2()
        {
            var filtro = new Uruz.FiltroFacturas
            {
                IdCliente = 10,
            };

            Expression <Func <Uruz.FacturaDTO, bool> > expr = x =>
                                                              SqlExpr.EqualsNullable.Invoke(x.IdCliente, filtro.IdCliente) &&
                                                              SqlExpr.EqualsNullable.Invoke(x.IdSucursal, filtro.IdSucursal)
            ;

            var pars = new SqlExprParams(expr.Parameters[0], null, false, "fac", new SqlFromList.ExprStrRawSql[0], ParamMode.EntityFramework, new SqlParamDic());

            var visitor = new SqlRewriteVisitor(pars);
            var ret     = visitor.Visit(expr);
            var apps    = RewriteVisitor.applications;

            var expected = "x => Raw(\"(\"fac\".\"IdCliente\" = @IdCliente)\")";
            var actual   = ret.ToString();

            Assert.AreEqual(expected, actual);
        }
示例#16
0
        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);
        }
示例#17
0
        /// <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 });
        }