Ejemplo n.º 1
0
            internal override SqlSource VisitJoin(SqlJoin join)
            {
                base.VisitJoin(join);
                switch (join.JoinType)
                {
                case SqlJoinType.Cross:
                case SqlJoinType.Inner:
                    // reducing either side would effect cardinality of results
                    break;

                case SqlJoinType.LeftOuter:
                case SqlJoinType.CrossApply:
                case SqlJoinType.OuterApply:
                    // may reduce to left if no references to the right
                    if (this.HasEmptySource(join.Right))
                    {
                        SqlAlias a = (SqlAlias)join.Right;
                        this.removedMap[a] = a;
                        return(join.Left);
                    }
                    break;
                }
                return(join);
            }
Ejemplo n.º 2
0
 internal override SqlSource VisitJoin(SqlJoin join)
 {
     this.ReferenceColumns(join.Condition);
     return(base.VisitJoin(join));
 }
Ejemplo n.º 3
0
            internal override SqlSource VisitSource(SqlSource source)
            {
                source = base.VisitSource(source);

                SqlJoin join = source as SqlJoin;

                if (join != null)
                {
                    if (join.JoinType == SqlJoinType.OuterApply)
                    {
                        // Reduce outer-apply into left-outer-join
                        HashSet <SqlAlias>      leftProducedAliases = SqlGatherProducedAliases.Gather(join.Left);
                        HashSet <SqlExpression> liftedExpressions   = new HashSet <SqlExpression>();

                        if (SqlPredicateLifter.CanLift(join.Right, leftProducedAliases, liftedExpressions) &&
                            SqlSelectionLifter.CanLift(join.Right, leftProducedAliases, liftedExpressions) &&
                            !SqlAliasDependencyChecker.IsDependent(join.Right, leftProducedAliases, liftedExpressions))
                        {
                            SqlExpression            liftedPredicate  = SqlPredicateLifter.Lift(join.Right, leftProducedAliases);
                            List <List <SqlColumn> > liftedSelections = SqlSelectionLifter.Lift(join.Right, leftProducedAliases, liftedExpressions);

                            join.JoinType  = SqlJoinType.LeftOuter;
                            join.Condition = liftedPredicate;

                            if (liftedSelections != null)
                            {
                                foreach (List <SqlColumn> selection in liftedSelections)
                                {
                                    source = this.PushSourceDown(source, selection);
                                }
                            }
                        }
                        else
                        {
                            this.AnnotateSqlIncompatibility(join, SqlProvider.ProviderMode.Sql2000);
                        }
                    }
                    else if (join.JoinType == SqlJoinType.CrossApply)
                    {
                        // reduce cross apply with special nested left-outer-join's into a single left-outer-join
                        //
                        // SELECT x.*, y.*
                        // FROM X
                        // CROSS APPLY (
                        //      SELECT y.*
                        //       FROM (
                        //          SELECT ?
                        //       )
                        //       LEFT OUTER JOIN (
                        //          SELECT y.* FROM Y
                        //       ) AS y
                        //
                        // ==>
                        //
                        // SELECT x.*, y.*
                        // FROM X
                        // LEFT OUTER JOIN (
                        //     SELECT y.* FROM Y
                        // )

                        SqlJoin leftOuter = this.GetLeftOuterWithUnreferencedSingletonOnLeft(join.Right);
                        if (leftOuter != null)
                        {
                            HashSet <SqlAlias>      leftProducedAliases = SqlGatherProducedAliases.Gather(join.Left);
                            HashSet <SqlExpression> liftedExpressions   = new HashSet <SqlExpression>();

                            if (SqlPredicateLifter.CanLift(leftOuter.Right, leftProducedAliases, liftedExpressions) &&
                                SqlSelectionLifter.CanLift(leftOuter.Right, leftProducedAliases, liftedExpressions) &&
                                !SqlAliasDependencyChecker.IsDependent(leftOuter.Right, leftProducedAliases, liftedExpressions)
                                )
                            {
                                SqlExpression            liftedPredicate  = SqlPredicateLifter.Lift(leftOuter.Right, leftProducedAliases);
                                List <List <SqlColumn> > liftedSelections = SqlSelectionLifter.Lift(leftOuter.Right, leftProducedAliases, liftedExpressions);

                                // add intermediate selections
                                this.GetSelectionsBeforeJoin(join.Right, liftedSelections);

                                // push down all selections
                                foreach (List <SqlColumn> selection in liftedSelections.Where(s => s.Count > 0))
                                {
                                    source = this.PushSourceDown(source, selection);
                                }

                                join.JoinType  = SqlJoinType.LeftOuter;
                                join.Condition = this.factory.AndAccumulate(leftOuter.Condition, liftedPredicate);
                                join.Right     = leftOuter.Right;
                            }
                            else
                            {
                                this.AnnotateSqlIncompatibility(join, SqlProvider.ProviderMode.Sql2000);
                            }
                        }
                    }

                    // re-balance join tree of left-outer-joins to expose LOJ w/ leftside unreferenced
                    while (join.JoinType == SqlJoinType.LeftOuter)
                    {
                        // look for buried left-outer-joined-with-unreferenced singleton
                        SqlJoin leftLeftOuter = this.GetLeftOuterWithUnreferencedSingletonOnLeft(join.Left);
                        if (leftLeftOuter == null)
                        {
                            break;
                        }

                        List <List <SqlColumn> > liftedSelections = new List <List <SqlColumn> >();

                        // add intermediate selections
                        this.GetSelectionsBeforeJoin(join.Left, liftedSelections);

                        // push down all selections
                        foreach (List <SqlColumn> selection in liftedSelections)
                        {
                            source = this.PushSourceDown(source, selection);
                        }

                        // bubble this one up on-top of this 'join'.
                        SqlSource     jRight     = join.Right;
                        SqlExpression jCondition = join.Condition;

                        join.Left      = leftLeftOuter.Left;
                        join.Right     = leftLeftOuter;
                        join.Condition = leftLeftOuter.Condition;

                        leftLeftOuter.Left      = leftLeftOuter.Right;
                        leftLeftOuter.Right     = jRight;
                        leftLeftOuter.Condition = jCondition;
                    }
                }

                return(source);
            }