/// <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()"); }
/// <summary> /// Converts an UNION clause to string /// </summary> static string UnionToStr(UnionClause clause, SqlExprParams pars) { var b = new StringBuilder(); var typeStr = clause.Type == UnionType.Union ? ( clause.Uniqueness == UnionUniqueness.All ? "UNION ALL" : "UNION" ) : clause.Type == UnionType.Intersect ? "INTERSECT" : clause.Type == UnionType.Except ? "EXCEPT" : throw new ArgumentException(); var queryStr = StatementStr.QueryToStr(clause.Query, pars.ParamMode, pars.ParamDic); b.AppendLine(typeStr); b.AppendLine("("); b.AppendLine(TabStr(queryStr.Sql)); b.Append(")"); return(b.ToString()); }