예제 #1
0
        /// <summary>
        /// Convierte un <see cref="MemberExpression"/> a SQL, tomando en cuenta los aliases de la lista de froms
        /// y la lógica descrita en <see cref="SqlExprParams"/>
        /// </summary>
        static string SingleMemberToSql(SqlExprParams pars, string baseMemberName, string subpath, MemberExpression mem)
        {
            var memberName = baseMemberName + subpath;

            if (pars.FromListNamed)
            {
                //Si la lista de FROM tiene aliases, el parametro del select no hace referencia a una tabla,
                //si no a un objeto de aliases donde cada propiedad es una tabla o un elemento de un JOIN
                MemberExpression firstExpr = mem;
                while (firstExpr is MemberExpression sm1 && sm1.Expression is MemberExpression sm2)
                {
                    firstExpr = sm2;
                }

                if (IsFromParam(mem.Expression))
                {
                    throw new ArgumentException("No esta soportado obtener una expresión de * en el SingleMemberSql");
                }
                else if (IsFromParam(firstExpr.Expression))
                {
                    return(TableRefToSql(firstExpr.Member.Name, memberName));
                }
                else if (IsRawTableRef(firstExpr.Expression, out var raw))
                {
                    return(RawTableRefToSql(raw, SqlSelect.ColNameToStr(memberName)));
                }
            }
            else
            {
                //Si la lista de FROM no tiene aliases, el parámetro del SELECT hace referencia a la tabla del SELECT

                Expression firstExpr = mem;
                while (firstExpr is MemberExpression sm)
                {
                    firstExpr = sm.Expression;
                }

                if (IsFromParam(firstExpr))
                {
                    return(TableRefToSql(pars.FromListAlias, memberName));
                }
                else if (IsRawTableRef(firstExpr, out var raw))
                {
                    return(RawTableRefToSql(raw, SqlSelect.ColNameToStr(memberName)));
                }
            }

            //Intentamos convertir al Expr a string con el replace:
            var exprRep = SqlFromList.ReplaceStringAliasMembers(mem.Expression, pars.Replace);

            if (exprRep != null)
            {
                return($"{exprRep}.\"{memberName}\"");
            }

            var exprStr = ExprToSql(mem.Expression, pars, false);

            return($"{exprStr}.\"{memberName}\"");
        }
예제 #2
0
        public static string SubqueryToSql(Expression expr, SqlExprParams pars)
        {
            var selectCall   = expr;
            var callSub      = SqlFromList.ReplaceSubqueryBody(selectCall, pars.Replace);
            var subqueryFunc = Expression.Lambda(callSub).Compile();
            var subqueryExec = (ISqlSelectHasClause)subqueryFunc.DynamicInvoke(new object[0]);

            var selectStr = SqlSelect.TabStr(SqlSelect.SelectToString(subqueryExec.Clause, pars.ParamMode, pars.ParamDic));

            return($"({Environment.NewLine}{selectStr}{Environment.NewLine})");
        }
예제 #3
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());
        }
예제 #4
0
        /// <summary>
        /// Convierte una cláusula de SELECT a string
        /// </summary>
        public static SelectToStrResult SelectToStringScalar(SelectClause clause, ParamMode paramMode, SqlParamDic paramDic)
        {
            var selectExpr = clause.Select;

            var paramName   = selectExpr.Parameters[0].Name;
            var from        = SqlFromList.FromListToStr(clause.From, paramName, true, paramMode, paramDic);
            var selectParam = selectExpr.Parameters[0];
            var aliases     = from.Aliases.ToList();

            if (!from.Named)
            {
                //Agregar el parametro del select como el nombre del fromList, esto para que se sustituya correctamente en los subqueries
                aliases.Add(new SqlFromList.ExprStrRawSql(selectParam, TableNameToStr(from.Alias)));
            }
            var pars = new SqlExprParams(selectParam, selectExpr.Parameters[1], from.Named, from.Alias, aliases, paramMode, paramDic);

            var select = SelectBodyToStr(selectExpr.Body, pars);

            //The query converted to string, before the PostUnion
            var query = new StringBuilder();

            query.Append("SELECT");
            if (clause.DistinctType != SelectType.All)
            {
                query.Append(" ");
                switch (clause.DistinctType)
                {
                case SelectType.Distinct:
                    query.Append("DISTINCT");
                    break;

                case SelectType.DistinctOn:
                    query.Append(DistinctOnStr(clause.DistinctOn, pars));
                    break;
                }
            }
            query.AppendLine();
            query.AppendLine($"{TabStr(SelectExprToStr(select.Values))}");
            query.AppendLine(from.Sql);
            if (clause.Where != null)
            {
                query.AppendLine(WhereStr(clause.Where, pars));
            }
            if (clause.GroupBy?.Any() == true)
            {
                query.AppendLine(GroupByStr(clause.GroupBy, pars));
            }
            if (clause.Window != null)
            {
                query.AppendLine(WindowToStr(clause.Window, pars));
            }
            if (clause.OrderBy?.Any() == true)
            {
                query.AppendLine(OrderByStr(clause.OrderBy, pars));
            }
            if (clause.Limit != null)
            {
                query.AppendLine("LIMIT " + clause.Limit);
            }

            //Delete the last line jump, note that the lenght of the line-jump
            //depends on the operating system
            query.Length = query.Length - Environment.NewLine.Length;

            StringBuilder ret;

            if (clause.Unions?.Any() == true)
            {
                ret = new StringBuilder();
                //Put the query whole inside parenthesis
                ret.AppendLine("(");
                ret.AppendLine(TabStr(query.ToString()));
                ret.AppendLine(")");

                foreach (var union in clause.Unions)
                {
                    ret.AppendLine(UnionToStr(union, pars));
                }

                //Remove the last lineJump:
                ret.Length = ret.Length - Environment.NewLine.Length;
            }
            else
            {
                ret = query;
            }
            return(new SelectToStrResult(ret.ToString(), select.Values.Select(x => x.Column).ToList(), select.Scalar));
        }