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