private void MapAliases(Expression a, Expression b)
        {
            DbTableAlias[] prodA = DeclaredAliasGatherer.Gather(a).ToArray();
            DbTableAlias[] prodB = DeclaredAliasGatherer.Gather(b).ToArray();

            for (int i = 0, n = prodA.Length; i < n; i++)
            {
                _aliasScope.Add(prodA[i], prodB[i]);
            }
        }
        protected override Expression VisitJoin(DbJoinExpression join)
        {
            join = (DbJoinExpression)base.VisitJoin(join);

            if (join.Join == DbJoinType.CrossApply || join.Join == DbJoinType.OuterApply)
            {
                if (join.Right is DbTableExpression)
                {
                    return(new DbJoinExpression(DbJoinType.CrossJoin, join.Left, join.Right, null));
                }
                else
                {
                    DbSelectExpression select = join.Right as DbSelectExpression;
                    // Only consider rewriting cross apply if
                    //   1) right side is a select
                    //   2) other than in the where clause in the right-side select, no left-side declared aliases are referenced
                    //   3) and has no behavior that would change semantics if the where clause is removed (like groups, aggregates, take, skip, etc).
                    // Note: it is best to attempt this after redundant subqueries have been removed.
                    if (select != null &&
                        select.Take == null &&
                        select.Skip == null &&
                        !AggregateChecker.HasAggregates(select) &&
                        (select.GroupBy == null || select.GroupBy.Count == 0))
                    {
                        DbSelectExpression     selectWithoutWhere = select.SetWhere(null);
                        HashSet <DbTableAlias> referencedAliases  = ReferencedAliasGatherer.Gather(selectWithoutWhere);
                        HashSet <DbTableAlias> declaredAliases    = DeclaredAliasGatherer.Gather(join.Left);
                        referencedAliases.IntersectWith(declaredAliases);
                        if (referencedAliases.Count == 0)
                        {
                            Expression where = select.Where;
                            select           = selectWithoutWhere;
                            var pc = ColumnProjector.ProjectColumns(this.CanBeColumn, where, select.Columns, select.Alias, DeclaredAliasGatherer.Gather(select.From));
                            select = select.SetColumns(pc.Columns);
                            where  = pc.Projector;
                            DbJoinType jt = (where == null) ? DbJoinType.CrossJoin :
                                            (join.Join == DbJoinType.CrossApply ? DbJoinType.InnerJoin : DbJoinType.LeftOuter);
                            return(new DbJoinExpression(jt, join.Left, select, where));
                        }
                    }
                }
            }

            return(join);
        }
예제 #3
0
 protected override Expression VisitJoin(DbJoinExpression join)
 {
     join = (DbJoinExpression)base.VisitJoin(join);
     if (join.Join == DbJoinType.CrossJoin && this.currentWhere != null)
     {
         // try to figure out which parts of the current where expression can be used for a join condition
         var declaredLeft  = DeclaredAliasGatherer.Gather(join.Left);
         var declaredRight = DeclaredAliasGatherer.Gather(join.Right);
         var declared      = new HashSet <DbTableAlias>(declaredLeft.Union(declaredRight));
         var exprs         = this.currentWhere.Split(ExpressionType.And, ExpressionType.AndAlso);
         var good          = exprs.Where(e => CanBeJoinCondition(e, declaredLeft, declaredRight, declared)).ToList();
         if (good.Count > 0)
         {
             var condition = good.Join(ExpressionType.And);
             join = this.UpdateJoin(join, DbJoinType.InnerJoin, join.Left, join.Right, condition);
             var newWhere = exprs.Where(e => !good.Contains(e)).Join(ExpressionType.And);
             this.currentWhere = newWhere;
         }
     }
     return(join);
 }
예제 #4
0
        private Expression MakeSubquery(Expression expression)
        {
            var newAlias = new DbTableAlias();
            var aliases  = DeclaredAliasGatherer.Gather(expression);

            var decls = new List <DbColumnDeclaration>();

            foreach (var ta in aliases)
            {
                foreach (var col in this.columns[ta])
                {
                    string name = decls.GetAvailableColumnName(col.Name);
                    var    decl = new DbColumnDeclaration(name, col);
                    decls.Add(decl);
                    var newCol = new DbColumnExpression(col.Type, col.DbType, newAlias, col.Name);
                    this.map.Add(col, newCol);
                }
            }

            return(new DbSelectExpression(newAlias, decls, expression, null));
        }
 public static HashSet<DbTableAlias> Gather(Expression source)
 {
     var gatherer = new DeclaredAliasGatherer();
     gatherer.Visit(source);
     return gatherer.aliases;
 }