using System.Linq.Expressions; using Connected.Expressions.Expressions; namespace Connected.Expressions.Translation.Resolvers; internal sealed class JoinColumnResolver { private JoinColumnResolver(HashSet aliases) { Aliases = aliases; Columns = new HashSet(); } private HashSet Aliases { get; } private HashSet Columns { get; } public static HashSet Resolve(HashSet aliases, SelectExpression select) { var resolver = new JoinColumnResolver(aliases); resolver.Resolve(select.Where); return resolver.Columns; } private void Resolve(Expression? expression) { if (expression is BinaryExpression b) { switch (b.NodeType) { case ExpressionType.Equal: case ExpressionType.NotEqual: if (IsExternalColumn(b.Left) && GetColumn(b.Right) is not null) { if (GetColumn(b.Right) is ColumnExpression right) Columns.Add(right); } else if (IsExternalColumn(b.Right) && GetColumn(b.Left) is not null) { if (GetColumn(b.Left) is ColumnExpression left) Columns.Add(left); } break; case ExpressionType.And: case ExpressionType.AndAlso: if (b.Type == typeof(bool) || b.Type == typeof(bool?)) { Resolve(b.Left); Resolve(b.Right); } break; } } } private static ColumnExpression? GetColumn(Expression exp) { while (exp.NodeType == ExpressionType.Convert) exp = ((UnaryExpression)exp).Operand; return exp as ColumnExpression; } private bool IsExternalColumn(Expression exp) { var col = GetColumn(exp); if (col is not null && !Aliases.Contains(col.Alias)) return true; return false; } }