예제 #1
0
        /// <summary>
        /// Obtiene el SQL de una referencia a una columna de una tabla.
        /// </summary>
        /// <param name="table">Si es null se devuelve sólo la columna sin el identificador de la tabla</param>
        /// <param name="column">Nombre de la columna. Puede ser * para indicar todas las columnas</param>
        static string TableRefToSql(string table, string column)
        {
            var colSql   = SqlSelect.ColNameToStr(column);
            var tableRaw = table != null ? $"\"{table}\"" : null;

            return(RawTableRefToSql(tableRaw, colSql));
        }
예제 #2
0
        /// <summary>
        /// Converts an <see cref="ISqlQuery"/> to string
        /// </summary>
        public static QueryToStrResult QueryToStr(ISqlQuery item, ParamMode paramMode, SqlParamDic paramDic)
        {
            if (item is ISqlSelectHasClause select)
            {
                var str = SqlSelect.SelectToStringScalar(select.Clause, paramMode, paramDic);
                return(new QueryColsToStrResult(str.Sql, str.Columns));
            }
            else if (item is ISqlWithSelect withSelect)
            {
                var withSql     = SqlWith.WithToSql(withSelect.With.With, withSelect.With.Param, paramMode, paramDic);
                var subquerySql = FromListTargetToStr(withSelect.Query, paramMode, paramDic);
                var ret         = $"{withSql}{Environment.NewLine}{subquerySql.Sql}";

                if (subquerySql is QueryColsToStrResult subCols)
                {
                    return(new QueryColsToStrResult(ret, subCols.Columns));
                }

                return(new QueryToStrResult(ret));
            }
            else if (item is ISqlSelectRaw subq)
            {
                return(new QueryToStrResult(SqlSelect.DetabStr(subq.Raw)));
            }
            throw new ArgumentException("El from item target debe de ser una tabla o un select");
        }
예제 #3
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}\"");
        }
예제 #4
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})");
        }
예제 #5
0
 /// <summary>
 /// Agrega los parentesis si subQ es true
 /// </summary>
 static string SubqueryParenthesis(StatementToStrResult fromList)
 {
     switch (fromList)
     {
         case QueryToStrResult _:
             return $"({Environment.NewLine}{SqlSelect.TabStr(fromList.Sql)}{Environment.NewLine})";
         case TableToStrResult _:
             return fromList.Sql;
         default:
             throw new ArgumentException();
     }
 }
예제 #6
0
        public static string ConditionalToSql(ConditionalExpression expr, SqlExprParams pars)
        {
            var b = new StringBuilder();

            Expression curr = expr;

            while (curr is ConditionalExpression cond)
            {
                b.Append("WHEN ");
                b.Append(ExprToSql(cond.Test, pars, false));
                b.Append(" THEN ");
                b.Append(ExprToSql(cond.IfTrue, pars, false));

                b.AppendLine();
                curr = cond.IfFalse;
            }

            b.Append("ELSE ");
            b.Append(ExprToSql(curr, pars, false));

            return(SqlSelect.TabStr($"{Environment.NewLine}CASE{Environment.NewLine}{SqlSelect.TabStr(b.ToString())}{Environment.NewLine}END"));
        }
예제 #7
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);
        }
예제 #8
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());
        }
예제 #9
0
 static (string sql, bool named) JoinToStr(IFromListItem item, Func<Expression, string> toSql, IReadOnlyList<ExprStrRawSql> replaceMembers, string paramName, bool forceUpperAlias, ParamMode paramMode, SqlParamDic paramDic)
 {
     var paramAlias = SqlSelect.TableNameToStr(paramName);
     return JoinToStrAlias(item, toSql, replaceMembers, paramAlias, forceUpperAlias, paramMode, paramDic);
 }