示例#1
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);
            }
        }
示例#2
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);
        }
示例#3
0
        /// <summary>
        /// Convierte la expresión de proyección de un SELECT a sql, devuelve si la proyección es escalar
        /// </summary>
        public static SelectExprToStrResult SelectBodyToStr(Expression body, SqlExprParams pars)
        {
            var visitor = new SqlRewriteVisitor(pars);

            body = visitor.Visit(body);

            IEnumerable <ValueCol> MemberAssigToSql(Expression expr, MemberInfo prop)
            {
                var exprSql = SqlExpression.ExprToSqlStar(expr, pars, false);

                if (exprSql.star)
                {
                    return(new[] {
                        new ValueCol(SqlExpression.SqlSubpath.Single(exprSql.sql), null)
                    });
                }

                var asList = exprSql.sql.Select(subpath =>
                                                new ValueCol(subpath.Sql, MemberToColumnName(prop, subpath))
                                                );

                return(asList);
            }

            if (body is MemberInitExpression || body is NewExpression)
            {
                var exprs = ExtractInitExpr(body)
                            .SelectMany(x => MemberAssigToSql(x.expr, x.mem))
                            .ToList()
                ;

                return(new SelectExprToStrResult(exprs, false));
            }

            var bodySql = SqlExpression.ExprToSqlStar(body, pars, false);

            if (bodySql.sql.Count > 1)
            {
                throw new ArgumentException("Por ahora no esta permitido devolver un ComplexType como el resultado de un SELECT");
            }
            return(new SelectExprToStrResult(
                       new[] {
                new ValueCol(bodySql.sql.First().Sql, null)
            },
                       !bodySql.star));
        }
示例#4
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);
        }
示例#5
0
        /// <summary>
        /// Convierte una lista de FROM a SQL.
        /// Devuelve si la lista de FROMs tiene aliases
        /// </summary>
        /// <param name="item">Elemento que representa ya sea a un FROM o a una lista de JOINS</param>
        /// <param name="toSql">Convierte una expresión a SQL</param>
        /// <param name="paramSql">Alias del parámetro en SQL</param>
        /// <returns></returns>
        static (string sql, bool named) JoinToStrAlias(IFromListItem item, Func<Expression, string> toSql, IReadOnlyList<ExprStrRawSql> replaceMembers, string paramSql, bool forceUpperAlias, ParamMode paramMode, SqlParamDic paramDic)
        {
            if (item is SqlJoin join)
            {
                var currentAlias = toSql(join.Map.Parameters[1]);
                var currentOnStr = toSql(join.On.Body);
                var leftParam = join.Map.Parameters[0];
                var leftAlias = ReplaceStringAliasMembers(leftParam, replaceMembers);
                var rightSubsNoRep = ReplaceSubqueryLambda(join.Right, leftParam, replaceMembers);

                //Visitar el lado derecho del JOIN:
                //TODO: Hacer una función para visitar a las expresiones de lado derecho del JOIN

                var rightSubs = SqlRewriteVisitor.VisitFromItem(rightSubsNoRep);

                var rightFunc = Expression.Lambda(rightSubs).Compile();
                var rightExec = (IFromListItemTarget)rightFunc.DynamicInvoke(new object[0]);

                var latStr = join.Lateral ? "LATERAL " : "";
                var typeStr =
                    join.Type == JoinType.Inner ? "" :
                    join.Type == JoinType.Left ? "LEFT " :
                    join.Type == JoinType.Right ? "RIGHT " :
                    join.Type == JoinType.Outter ? "OUTTER " :
                    join.Type == JoinType.Cross ? "CROSS " :
                    throw new ArgumentException("Join type " + join.Type + " invalido");

                var right = $"{typeStr}JOIN {latStr}{SubqueryParenthesis(StatementStr.StatementToString(rightExec, paramMode, paramDic))} {currentAlias} ON {currentOnStr}";

                var leftStr = JoinToStrAlias(join.Left, toSql, replaceMembers, leftAlias, true, paramMode, paramDic);
                return (leftStr.sql + Environment.NewLine + right, true);
            }
            else if (item is ISqlFrom from)
            {
                var fromIt = StatementStr.StatementToString(from.Target, paramMode, paramDic);
                return ($"FROM {SubqueryParenthesis(fromIt)} {(((fromIt is QueryToStrResult) || forceUpperAlias) ? paramSql : "")}", false);
            }
            else if (item is FromListAlias alias)
            {
                return JoinToStrAlias(alias.From, toSql, replaceMembers, paramSql, forceUpperAlias, paramMode, paramDic);
            }

            throw new ArgumentException("El from-item debe de ser un JOIN, FROM o Alias()");
        }
示例#6
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());
        }
示例#7
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);
            }
        }
示例#8
0
        /// <summary>
        /// Convierte el cuerpo de la expresión SET a SQL
        /// </summary>
        public static string SetToSql(Expression body,
                                      ParamMode paramMode,
                                      SqlParamDic paramDic,
                                      IEnumerable <SqlFromList.ExprStrRawSql> exprAlias
                                      )
        {
            var b    = new StringBuilder();
            var pars = new SqlExprParams(null, null, false, null, exprAlias.ToList(), paramMode, paramDic);

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

            body = visitor.Visit(body);

            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));
            var sets     = subpaths.Select(x => (
                                               column: SqlSelect.MemberToColumnName(x.member, x.subpath),
                                               value: x.subpath.Sql))
            ;

            var setSql = sets
                         .Select(x =>
                                 $"{SqlSelect.ColNameToStr(x.column)} = {x.value}"
                                 );

            var sql = string.Join($", {Environment.NewLine}", setSql);

            return(sql);
        }
示例#9
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);
        }
示例#10
0
        /// <summary>
        /// Convierte una expresión a SQL
        /// </summary>
        public static (IReadOnlyList <SqlSubpath> sql, bool star) ExprToSqlStar(Expression expr, SqlExprParams pars, bool rewrite)
        {
            if (rewrite)
            {
                var visitor = new SqlRewriteVisitor(pars);
                expr = visitor.Visit(expr);
            }
            //Es importante primero comprobar la igualdad del parametro, ya que el replace list tiene una entrada para el parametro tambien
            if (IsFromParam(expr))
            {
                if (pars.FromListNamed)
                {
                    return(SqlSubpath.FromString($"*"), true);
                }

                return(SqlSubpath.FromString(SqlExpression.TableRefToSql(pars.FromListAlias, "*")), true);
            }

            var replace = SqlFromList.ReplaceStringAliasMembers(expr, pars.Replace);

            if (replace != null)
            {
                return(SqlSubpath.FromString(replace), false);
            }

            if (expr is MemberExpression mem)
            {
                return(MemberToSql(mem, pars));
            }
            else if (expr is ConditionalExpression cond)
            {
                return(SqlSubpath.FromString(ConditionalToSql(cond, pars)), false);
            }
            else if (expr is MethodCallExpression call)
            {
                return(SqlSubpath.FromString(CallToSql(call, pars)), false);
            }
            else if (expr is MemberInitExpression || expr is NewExpression)
            {
                //TODO: Note la similaridad de este código, del InsertToString y del SelectStr
                //Puede ser que estas 3 funciones sean lógicamente equivalentes y que se puedan unificar

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

                if (exprs.Any(y => y.sql.star))
                {
                    throw new ArgumentException("No esta soportado una expresión star '*' en una subexpresión");
                }

                var subpaths = exprs
                               .SelectMany(x => x.sql.sql, (parent, child) => (member: parent.mem, subpath: child))
                               .Select(x => new SqlSubpath(x.subpath.Sql, "_" + x.member.Name + x.subpath.Subpath))
                               .ToList()
                ;

                return(subpaths, false);
            }
            throw new ArgumentException("No se pudo convertir a SQL la expresión " + expr.ToString());
        }