Пример #1
0
        protected override BoundRelation RewriteJoinRelation(BoundJoinRelation node)
        {
            if (node.JoinType == BoundJoinType.RightOuter)
            {
                var newLeft  = node.Right;
                var newRight = node.Left;
                node = node.Update(BoundJoinType.LeftOuter, newLeft, newRight, node.Condition, node.Probe, node.PassthruPredicate);
            }

            return(base.RewriteJoinRelation(node));
        }
Пример #2
0
        protected override BoundRelation RewriteJoinRelation(BoundJoinRelation node)
        {
            var left  = RewriteRelation(node.Left);
            var right = RewriteRelation(node.Right);

            var rewrittenRight = RewriteConjunctions(right, node.Condition);

            if (rewrittenRight != null)
            {
                // We might have residual subqueries that couldn't be
                // converted to semi joins.
                return(RewriteRelation(node.Update(node.JoinType, left, rewrittenRight, null, node.Probe, node.PassthruPredicate)));
            }

            // There were no subqueries that could be expressed as semi joins.
            // However, there might still exist subqueries, so we need to visit
            // the expression that will convert them to probing semi joins.

            var condition       = RewriteExpression(node.Condition);
            var rightWithProbes = RewriteInputWithSubqueries(right);

            return(node.Update(node.JoinType, left, rightWithProbes, condition, node.Probe, node.PassthruPredicate));
        }
Пример #3
0
        protected override BoundRelation RewriteJoinRelation(BoundJoinRelation node)
        {
            var newLeft = RewriteRelation(node.Left);

            bool semiJoinContext;

            semiJoinContext = (node.JoinType == BoundJoinType.LeftSemi ||
                               node.JoinType == BoundJoinType.LeftAntiSemi);
            _semiJoinContextFlagStack.Push(semiJoinContext);
            var newRight = RewriteRelation(node.Right);

            _semiJoinContextFlagStack.Pop();

            return(node.Update(node.JoinType, newLeft, newRight, node.Condition, node.Probe, node.PassthruPredicate));
        }
Пример #4
0
        protected override BoundRelation RewriteJoinRelation(BoundJoinRelation node)
        {
            if (node.Condition != null && node.Probe == null)
            {
                BoundExpression pushedLeft  = null;
                BoundExpression pushedRight = null;
                BoundExpression remainder   = null;

                foreach (var conjunction in Expression.SplitConjunctions(node.Condition))
                {
                    if (AllowsLeftPushDown(node.JoinType) && !conjunction.DependsOnAny(node.Right.GetOutputValues()))
                    {
                        pushedLeft = Expression.And(pushedLeft, conjunction);
                    }
                    else if (AllowsRightPushDown(node.JoinType) && !conjunction.DependsOnAny(node.Left.GetOutputValues()))
                    {
                        pushedRight = Expression.And(pushedRight, conjunction);
                    }
                    else
                    {
                        remainder = Expression.And(remainder, conjunction);
                    }
                }

                var newLeft = pushedLeft == null
                    ? node.Left
                    : new BoundFilterRelation(node.Left, pushedLeft);

                var newRight = pushedRight == null
                    ? node.Right
                    : new BoundFilterRelation(node.Right, pushedRight);

                var newNode = node.Update(node.JoinType,
                                          RewriteRelation(newLeft),
                                          RewriteRelation(newRight),
                                          remainder,
                                          RewriteValueSlot(node.Probe),
                                          RewriteExpression(node.PassthruPredicate));
                return(newNode);
            }

            return(base.RewriteJoinRelation(node));
        }
Пример #5
0
        protected override BoundRelation RewriteJoinRelation(BoundJoinRelation node)
        {
            // Get declared tables of left and right

            var leftDefinedValues  = node.Left.GetDefinedValues().ToImmutableArray();
            var rightDefinedValues = node.Right.GetDefinedValues().ToImmutableArray();

            // Replace outer joins by left-/right-/inner joins

            if (node.JoinType == BoundJoinType.RightOuter ||
                node.JoinType == BoundJoinType.FullOuter)
            {
                if (IsAnyNullRejected(leftDefinedValues))
                {
                    var newType = node.JoinType == BoundJoinType.RightOuter
                        ? BoundJoinType.Inner
                        : BoundJoinType.LeftOuter;

                    node = node.Update(newType, node.Left, node.Right, node.Condition, node.Probe, node.PassthruPredicate);
                }
            }

            if (node.JoinType == BoundJoinType.LeftOuter ||
                node.JoinType == BoundJoinType.FullOuter)
            {
                if (IsAnyNullRejected(rightDefinedValues))
                {
                    var newType = node.JoinType == BoundJoinType.LeftOuter
                        ? BoundJoinType.Inner
                        : BoundJoinType.RightOuter;

                    node = node.Update(newType, node.Left, node.Right, node.Condition, node.Probe, node.PassthruPredicate);
                }
            }

            // After converting an outer join to an inner one we can
            // sometimes eliminate the whole join.

            if (node.JoinType == BoundJoinType.Inner)
            {
                if (node.Left is BoundConstantRelation && !node.Left.GetDefinedValues().Any())
                {
                    return(RewriteRelation(WrapWithFilter(node.Right, node.Condition)));
                }

                if (node.Right is BoundConstantRelation && !node.Right.GetDefinedValues().Any())
                {
                    return(RewriteRelation(WrapWithFilter(node.Left, node.Condition)));
                }
            }

            // Analyze AND-parts of Condition

            if (node.JoinType != BoundJoinType.FullOuter)
            {
                var dependencyFinder = new ValueSlotDependencyFinder();

                foreach (var conjunction in Expression.SplitConjunctions(node.Condition))
                {
                    // Check if we can derive from this conjunction that a table it depends on
                    // is null-rejected.

                    dependencyFinder.ValueSlots.Clear();
                    dependencyFinder.VisitExpression(conjunction);

                    var slots             = dependencyFinder.ValueSlots;
                    var nullRejectedSlots = slots.Where(v => NullRejection.IsRejectingNull(conjunction, v));

                    foreach (var valueSlot in nullRejectedSlots)
                    {
                        if (node.JoinType != BoundJoinType.LeftOuter && leftDefinedValues.Contains(valueSlot))
                        {
                            AddNullRejectedTable(valueSlot);
                        }
                        else if (node.JoinType != BoundJoinType.RightOuter && rightDefinedValues.Contains(valueSlot))
                        {
                            AddNullRejectedTable(valueSlot);
                        }
                    }
                }
            }

            // Visit children

            return(base.RewriteJoinRelation(node));
        }
Пример #6
0
        private BoundRelation MergeWithOrPushOverJoin(BoundFilterRelation node, BoundJoinRelation input)
        {
            // TODO: Right now, we're not pushing over a join if it has any probing.
            //
            //       That might be too restristive. It should be OK to push a over
            //       a join to the side that isn't affecting the probe column.
            //
            //       In other words:
            //
            //       * pushing to the left is OK if it's a left (anti) semi join
            //       * pushing to the right is OK if it's a right (anti) semi join

            if (input.Probe != null)
            {
                return(node.Update(RewriteRelation(input), node.Condition));
            }

            if (AllowsMerge(input.JoinType))
            {
                var newCondition = Expression.And(input.Condition, node.Condition);
                var newInput     = input.Update(input.JoinType, input.Left, input.Right, newCondition, null, null);
                return(RewriteRelation(newInput));
            }
            else
            {
                BoundExpression pushedLeft  = null;
                BoundExpression pushedRight = null;
                BoundExpression remainder   = null;

                foreach (var conjunction in Expression.SplitConjunctions(node.Condition))
                {
                    if (AllowsLeftPushOver(input.JoinType) && !conjunction.DependsOnAny(input.Right.GetOutputValues()))
                    {
                        pushedLeft = Expression.And(pushedLeft, conjunction);
                    }
                    else if (AllowsRightPushOver(input.JoinType) && !conjunction.DependsOnAny(input.Left.GetOutputValues()))
                    {
                        pushedRight = Expression.And(pushedRight, conjunction);
                    }
                    else
                    {
                        remainder = Expression.And(remainder, conjunction);
                    }
                }

                var newLeft = pushedLeft == null
                    ? input.Left
                    : new BoundFilterRelation(input.Left, pushedLeft);

                var newRight = pushedRight == null
                    ? input.Right
                    : new BoundFilterRelation(input.Right, pushedRight);

                var newInput = input.Update(input.JoinType,
                                            RewriteRelation(newLeft),
                                            RewriteRelation(newRight),
                                            input.Condition,
                                            RewriteValueSlot(input.Probe),
                                            RewriteExpression(input.PassthruPredicate));

                var newNode = remainder == null
                    ? (BoundRelation)newInput
                    : node.Update(newInput, remainder);

                return(newNode);
            }
        }