예제 #1
0
        private bool CanBeJoinCondition(Expression expression, HashSet <TableAlias> left, HashSet <TableAlias> right, HashSet <TableAlias> all)
        {
            var referenced = DbReferencedAliasGatherer.Gather(expression);
            var leftOkay   = referenced.Intersect(left).Any();
            var rightOkay  = referenced.Intersect(right).Any();
            var subset     = referenced.IsSubsetOf(all);

            return(leftOkay && rightOkay && subset);
        }
        public static HashSet <TableAlias> Gather(Expression source)
        {
            var gatherer = new DbReferencedAliasGatherer();

            if (gatherer != null)
            {
                gatherer.Visit(source);
            }

            return(gatherer.aliases);
        }
        private bool GetEquiJoinKeyExpressions(Expression predicate, TableAlias outerAlias, List <Expression> outerExpressions, List <Expression> innerExpressions)
        {
            if (predicate.NodeType == ExpressionType.Equal)
            {
                var b        = predicate as BinaryExpression;
                var leftCol  = this.GetColumnExpression(b.Left);
                var rightCol = this.GetColumnExpression(b.Right);

                if (leftCol != null && rightCol != null)
                {
                    if (leftCol.Alias == outerAlias)
                    {
                        outerExpressions.Add(b.Left);
                        innerExpressions.Add(b.Right);

                        return(true);
                    }
                    else if (rightCol.Alias == outerAlias)
                    {
                        innerExpressions.Add(b.Left);
                        outerExpressions.Add(b.Right);

                        return(true);
                    }
                }
            }

            var hadKey = false;
            var parts  = predicate.Split(ExpressionType.And, ExpressionType.AndAlso);

            if (parts.Length > 1)
            {
                foreach (var part in parts)
                {
                    var hasOuterAliasReference = DbReferencedAliasGatherer.Gather(part).Contains(outerAlias);

                    if (hasOuterAliasReference)
                    {
                        if (GetEquiJoinKeyExpressions(part, outerAlias, outerExpressions, innerExpressions) == false)
                        {
                            return(false);
                        }

                        hadKey = true;
                    }
                }
            }

            return(hadKey);
        }
예제 #4
0
        protected override Expression VisitJoin(DbJoinExpression join)
        {
            join = base.VisitJoin(join) as DbJoinExpression;

            if (join.JoinType == JoinType.CrossApply || join.JoinType == JoinType.OuterApply)
            {
                if (join.Right is DbTableExpression)
                {
                    return(new DbJoinExpression(JoinType.CrossJoin, join.Left, join.Right, null));
                }

                if (join.Right is DbSelectExpression select && select.Take == null && select.Skip == null && !DbAggregateChecker.HasAggregates(select) && (select.GroupBy == null || select.GroupBy.Count == 0))
                {
                    var selectWithoutWhere = select.SetWhere(null);
                    var referencedAliases  = DbReferencedAliasGatherer.Gather(selectWithoutWhere);
                    var declaredAliases    = DbDeclaredAliasGatherer.Gather(join.Left);

                    if (referencedAliases != null)
                    {
                        referencedAliases.IntersectWith(declaredAliases);
                    }

                    if (referencedAliases.Count == 0)
                    {
                        var where = select.Where;

                        select = selectWithoutWhere;

                        var pc = DbColumnProjector.ProjectColumns(this.language, where, select.Columns, select.Alias, DbDeclaredAliasGatherer.Gather(select.From));

                        select = select.SetColumns(pc.Columns);

                        where = pc.Projector;

                        var jt = (where == null) ? JoinType.CrossJoin : (join.JoinType == JoinType.CrossApply ? JoinType.InnerJoin : JoinType.LeftOuter);

                        return(new DbJoinExpression(jt, join.Left, select, where));
                    }
                }
            }

            return(join);
        }