/// <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)); }
/// <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"); }
/// <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}\""); }
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})"); }
/// <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(); } }
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")); }
/// <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); }
/// <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()); }
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); }