Beispiel #1
0
        public static bool DependsOnAny(this BoundExpression condition, IEnumerable <ValueSlot> valueSlots)
        {
            var finder = new ValueSlotDependencyFinder();

            finder.VisitExpression(condition);
            return(finder.ValueSlots.Overlaps(valueSlots));
        }
Beispiel #2
0
        private bool ConjunctionHasOuterReference(HashSet <ValueSlot> definedValueSet, BoundExpression conjunction)
        {
            var valueSlotFinder = new ValueSlotDependencyFinder();

            valueSlotFinder.VisitExpression(conjunction);
            return(!valueSlotFinder.ValueSlots.All(definedValueSet.Contains));
        }
Beispiel #3
0
        public static IEnumerable <ValueSlot> GetOuterReferences(BoundJoinRelation node)
        {
            var valueSlotDependencyFinder = new ValueSlotDependencyFinder();

            valueSlotDependencyFinder.VisitRelation(node.Right);
            var usedValueSlots = valueSlotDependencyFinder.ValueSlots;

            return(node.Left.GetDefinedValues().Where(usedValueSlots.Contains));
        }
Beispiel #4
0
        private static void BuildGraph(List <BoundRelation> relations, List <BoundExpression> predicates, out ICollection <JoinNode> nodes, out ICollection <JoinEdge> edges)
        {
            var nodeByRelation = relations.Select(r => new JoinNode(r)).ToDictionary(n => n.Relation);

            nodes = nodeByRelation.Values;
            edges = new List <JoinEdge>();
            var edgeByNodes = new Dictionary <ValueTuple <JoinNode, JoinNode>, JoinEdge>();

            var relationByValueSlot = relations.SelectMany(r => r.GetDefinedValues(), ValueTuple.Create)
                                      .ToDictionary(t => t.Item2, t => t.Item1);

            var dependencyFinder = new ValueSlotDependencyFinder();

            foreach (var predicate in predicates)
            {
                dependencyFinder.ValueSlots.Clear();
                dependencyFinder.VisitExpression(predicate);

                var referencedSlots     = dependencyFinder.ValueSlots;
                var referencedRelations = referencedSlots.Where(v => relationByValueSlot.ContainsKey(v))
                                          .Select(v => relationByValueSlot[v])
                                          .ToImmutableArray();

                if (referencedRelations.Length == 2)
                {
                    var left      = nodeByRelation[referencedRelations[0]];
                    var right     = nodeByRelation[referencedRelations[1]];
                    var leftRight = ValueTuple.Create(left, right);
                    var rightLeft = ValueTuple.Create(right, left);

                    JoinEdge edge;
                    if (!edgeByNodes.TryGetValue(leftRight, out edge))
                    {
                        if (!edgeByNodes.TryGetValue(rightLeft, out edge))
                        {
                            edge = new JoinEdge(left, right);

                            left.Edges.Add(edge);
                            right.Edges.Add(edge);

                            edges.Add(edge);
                            edgeByNodes.Add(leftRight, edge);
                        }
                    }

                    edge.Conditions.Add(predicate);
                }
            }
        }
Beispiel #5
0
        protected override BoundRelation RewriteFilterRelation(BoundFilterRelation node)
        {
            // Check for null rejecting conditions.

            var dependencyFinder = new ValueSlotDependencyFinder();

            foreach (var conjunction in Expression.SplitConjunctions(node.Condition))
            {
                dependencyFinder.ValueSlots.Clear();
                dependencyFinder.VisitExpression(conjunction);

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

                foreach (var valueSlot in nullRejectedSlots)
                {
                    AddNullRejectedTable(valueSlot);
                }
            }

            return(base.RewriteFilterRelation(node));
        }
Beispiel #6
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));
        }
Beispiel #7
0
 public ValueSlotRecorder()
 {
     _finder = new ValueSlotDependencyFinder(UsedValueSlots);
 }