Exemple #1
0
        private void ExtractRelationsAndPredicates(BoundRelation node, out List <BoundRelation> relations, out List <BoundExpression> predicates)
        {
            relations  = new List <BoundRelation>();
            predicates = new List <BoundExpression>();

            var stack = new Stack <BoundRelation>();

            stack.Push(node);

            while (stack.Count > 0)
            {
                var current = stack.Pop();
                var join    = current as BoundJoinRelation;
                if (join == null || join.JoinType != BoundJoinType.Inner)
                {
                    // NOTE: We generally want to rewrite joins that we can't extract
                    //       ourselves. However, we've to be careful not rewrite the
                    //       node that we started from -- otherwise we stack overflow.
                    var rewrittenCurrent = current == node ? current : RewriteRelation(current);
                    relations.Add(rewrittenCurrent);
                }
                else
                {
                    if (join.Condition != null)
                    {
                        var conjunctions = Expression.SplitConjunctions(join.Condition);
                        predicates.AddRange(conjunctions);
                    }

                    stack.Push(join.Right);
                    stack.Push(join.Left);
                }
            }
        }
 public Subquery(SubqueryKind kind, ValueSlot valueSlot, BoundRelation relation, BoundExpression passthru)
 {
     Kind      = kind;
     ValueSlot = valueSlot;
     Relation  = relation;
     Passthru  = passthru;
 }
        public static bool ContainsSubquery(BoundRelation node)
        {
            var checker = new SubqueryChecker();

            checker.VisitRelation(node);
            return(checker.SubqueryFound);
        }
Exemple #4
0
        private static BoundRelation Optimize(BoundRelation relation)
        {
            foreach (var step in GetOptimizationSteps())
            {
                relation = step.RewriteRelation(relation);
            }

            return(relation);
        }
        public override void VisitRelation(BoundRelation node)
        {
            if (SubqueryFound)
            {
                return;
            }

            base.VisitRelation(node);
        }
        private static BoundRelation RewriteConjunctions(BoundRelation input, BoundExpression condition)
        {
            var current          = input;
            var scalarPredicates = new List <BoundExpression>();
            var conjunctions     = Expression.SplitConjunctions(condition);

            foreach (var conjunction in conjunctions)
            {
                BoundExistsSubselect exists;
                bool isNegated;
                if (TryGetExistsSubselect(conjunction, out exists, out isNegated))
                {
                    var joinType = isNegated
                        ? BoundJoinType.LeftAntiSemi
                        : BoundJoinType.LeftSemi;
                    current = new BoundJoinRelation(joinType, current, exists.Relation, null, null, null);
                }
                else if (Expression.IsDisjunction(conjunction))
                {
                    var relation = RewriteDisjunctions(conjunction);
                    if (relation != null)
                    {
                        current = new BoundJoinRelation(BoundJoinType.LeftSemi, current, relation, null, null, null);
                    }
                    else
                    {
                        scalarPredicates.Add(conjunction);
                    }
                }
                else
                {
                    scalarPredicates.Add(conjunction);
                }
            }

            // If we haven't done anything, simply return null to indicate to our
            // caller that the condition only contained scalars.

            if (current == input)
            {
                return(null);
            }

            // If we have no scalar predicates left, it means the condition only
            // contained EXISTs queries, so we can return the current node.

            if (scalarPredicates.Count == 0)
            {
                return(current);
            }

            // Othwerwise We add a filter for the scalars.

            var predicate = Expression.And(scalarPredicates);

            return(new BoundFilterRelation(current, predicate));
        }
Exemple #7
0
        public override BoundRelation RewriteRelation(BoundRelation node)
        {
            if (_recorder == null)
            {
                _recorder = new ValueSlotRecorder();
                _recorder.Record(node.GetOutputValues());
            }

            return(base.RewriteRelation(node));
        }
        private Iterator BuildRelation(BoundRelation relation)
        {
            switch (relation.Kind)
            {
            case BoundNodeKind.ConstantRelation:
                return(BuildConstant());

            case BoundNodeKind.TableRelation:
                return(BuildTable((BoundTableRelation)relation));

            case BoundNodeKind.JoinRelation:
                return(BuildJoin((BoundJoinRelation)relation));

            case BoundNodeKind.HashMatchRelation:
                return(BuildHashMatch((BoundHashMatchRelation)relation));

            case BoundNodeKind.FilterRelation:
                return(BuildFilter((BoundFilterRelation)relation));

            case BoundNodeKind.ComputeRelation:
                return(BuildCompute((BoundComputeRelation)relation));

            case BoundNodeKind.TopRelation:
                return(BuildTop((BoundTopRelation)relation));

            case BoundNodeKind.SortRelation:
                return(BuildSort((BoundSortRelation)relation));

            case BoundNodeKind.ConcatenationRelation:
                return(BuildConcatenationRelation((BoundConcatenationRelation)relation));

            case BoundNodeKind.StreamAggregatesRelation:
                return(BuildStreamAggregatesRelation((BoundStreamAggregatesRelation)relation));

            case BoundNodeKind.ProjectRelation:
                return(BuildProject((BoundProjectRelation)relation));

            case BoundNodeKind.AssertRelation:
                return(BuildAssert((BoundAssertRelation)relation));

            case BoundNodeKind.TableSpoolPusher:
                return(BuildTableSpoolPusher((BoundTableSpoolPusher)relation));

            case BoundNodeKind.TableSpoolPopper:
                return(BuildTableSpoolPopper((BoundTableSpoolPopper)relation));

            default:
                throw ExceptionBuilder.UnexpectedValue(relation.Kind);
            }
        }
        public override BoundRelation RewriteRelation(BoundRelation node)
        {
            _subqueryStack.Push(new List <Subquery>());

            var result = base.RewriteRelation(node);

            if (_subqueryStack.Peek().Any())
            {
                throw ExceptionBuilder.UnexpectedValue(node.Kind);
            }

            _subqueryStack.Pop();

            return(result);
        }
        private BoundRelation RewriteInputWithSubqueries(BoundRelation input)
        {
            var subqueries = _subqueryStack.Peek();
            var result     = input;

            result = subqueries.Where(s => s.Kind == SubqueryKind.Exists)
                     .Aggregate(result, EmitExists);

            result = subqueries.Where(s => s.Kind == SubqueryKind.Subselect)
                     .Aggregate(result, EmitSubselect);

            subqueries.Clear();

            return(result);
        }
Exemple #11
0
        private bool IsInstantiatedCommonTableExpression(BoundRelation boundRelation)
        {
            if (_symbol == null)
            {
                return(false);
            }

            var tableRelation = boundRelation as BoundTableRelation;

            if (tableRelation == null)
            {
                return(false);
            }

            return(tableRelation.TableInstance.Table == _symbol);
        }
Exemple #12
0
        private static BoundRelation AssembleJoin(ICollection <JoinNode> nodes, ICollection <JoinEdge> edges)
        {
            var nodeComparer = Comparer <JoinNode> .Create(CompareNode);

            var remainingNodes = new HashSet <JoinNode>(nodes);
            var remainingEdges = new HashSet <JoinEdge>(edges);
            var candidateNodes = new HashSet <JoinNode>();

            BoundRelation result = null;

            while (remainingNodes.Count > 0)
            {
                var start = remainingNodes.OrderBy(n => n, nodeComparer).First();
                remainingNodes.Remove(start);

                var relation = start.Relation;

                candidateNodes.UnionWith(start.Edges.Select(e => e.Other(start)));

                while (candidateNodes.Count > 0)
                {
                    var usableEdges = candidateNodes.SelectMany(n => n.Edges)
                                      .Where(e => remainingEdges.Contains(e))
                                      .Where(n => !remainingNodes.Contains(n.Left) || !remainingNodes.Contains(n.Right))
                                      .Where(e => e.Conditions.Any(IsRelation))
                                      .ToImmutableArray();

                    if (!usableEdges.Any())
                    {
                        usableEdges = candidateNodes.SelectMany(n => n.Edges)
                                      .Where(e => remainingEdges.Contains(e))
                                      .Where(n => !remainingNodes.Contains(n.Left) || !remainingNodes.Contains(n.Right))
                                      .ToImmutableArray();
                    }

                    var nextNode = usableEdges.SelectMany(e => new[] { e.Left, e.Right })
                                   .Where(candidateNodes.Contains)
                                   .OrderBy(n => n, nodeComparer)
                                   .FirstOrDefault();

                    if (nextNode != null)
                    {
                        candidateNodes.Remove(nextNode);
                        candidateNodes.UnionWith(nextNode.Edges.Select(e => e.Other(nextNode)).Where(n => remainingNodes.Contains(n)));

                        var edge = usableEdges.First(e => !remainingNodes.Contains(e.Left) && e.Right == nextNode ||
                                                     !remainingNodes.Contains(e.Right) && e.Left == nextNode);

                        remainingNodes.Remove(nextNode);
                        remainingEdges.Remove(edge);

                        var left      = relation;
                        var right     = nextNode.Relation;
                        var condition = Expression.And(edge.Conditions);
                        relation = new BoundJoinRelation(BoundJoinType.Inner, left, right, condition, null, null);
                    }
                }

                result = result == null
                    ? relation
                    : new BoundJoinRelation(BoundJoinType.Inner, result, relation, null, null, null);
            }

            Debug.Assert(remainingNodes.Count == 0, @"Found remaining nodes");

            // Add filter for remaining predicates

            var remainingPredicates = remainingEdges.SelectMany(e => e.Conditions);
            var remainingCondition  = Expression.And(remainingPredicates);

            if (remainingCondition != null)
            {
                result = new BoundFilterRelation(result, remainingCondition);
            }

            return(result);
        }
        public static Iterator Build(BoundRelation relation)
        {
            var builder = new IteratorBuilder();

            return(builder.BuildRelation(relation));
        }
 private static BoundJoinRelation EmitSubselect(BoundRelation result, Subquery subselect)
 {
     return(new BoundJoinRelation(BoundJoinType.LeftOuter, result, subselect.Relation, null, null, subselect.Passthru));
 }
 private static BoundJoinRelation EmitExists(BoundRelation result, Subquery existsSubquery)
 {
     return(new BoundJoinRelation(BoundJoinType.LeftSemi, result, existsSubquery.Relation, null, existsSubquery.ValueSlot, existsSubquery.Passthru));
 }
 private RowBufferAllocation BuildRowBufferAllocation(BoundRelation input, RowBuffer rowBuffer)
 {
     return(new RowBufferAllocation(_outerRowBufferAllocation, rowBuffer, input.GetOutputValues()));
 }
Exemple #17
0
 public override BoundRelation RewriteRelation(BoundRelation node)
 {
     AddValueSlotMapping(node.GetDefinedValues());
     return(base.RewriteRelation(node));
 }
Exemple #18
0
        public static BoundRelation Instantiate(BoundRelation relation, IEnumerable <KeyValuePair <ValueSlot, ValueSlot> > mapping)
        {
            var valueSlotRewriter = new ValueSlotRewriter(mapping);

            return(valueSlotRewriter.RewriteRelation(relation));
        }
Exemple #19
0
 public static BoundRelation Instantiate(BoundRelation relation)
 {
     return(Instantiate(relation, Enumerable.Empty <KeyValuePair <ValueSlot, ValueSlot> >()));
 }
Exemple #20
0
        private BoundRelation InstantiateRecursiveCommonTableExpression(ImmutableArray <ValueSlot> outputValues, CommonTableExpressionSymbol symbol)
        {
            // TableSpoolPusher
            //     Concat
            //         Compute (Recursion := 0)
            //             <Anchor>
            //         Assert (Recursion <= 100)
            //             Inner Join
            //                 Compute (Recursion := Recursion + 1)
            //                     TableSpoolPopper
            //                 Concat
            //                      Filter <RecursiveJoinPredicate1>
            //                          <RecursiveMember1>
            //                      Filter <RecursiveJoinPredicate2>
            //                          <RecursiveMember2>

            var valueSlotFactory = outputValues.First().Factory;

            // Create output values

            var unionRecusionSlot = valueSlotFactory.CreateTemporary(typeof(int));
            var concatValueSlots  = outputValues.Add(unionRecusionSlot);

            // Create anchor

            var anchor       = RewriteRelation(Instatiator.Instantiate(symbol.Anchor.Relation));
            var anchorValues = anchor.GetOutputValues().ToImmutableArray();

            var initRecursionSlot       = valueSlotFactory.CreateTemporary(typeof(int));
            var initRecursionDefinition = new BoundComputedValue(Expression.Literal(0), initRecursionSlot);
            var initRecursion           = new BoundComputeRelation(anchor, ImmutableArray.Create(initRecursionDefinition));

            var initRecursionOutputs = anchorValues.Add(initRecursionSlot);

            // Create TableSpoolPopper

            var tableSpoolPopperSlots = initRecursionOutputs.Select(v => v.Duplicate()).ToImmutableArray();

            var tableSpoolPopper = new BoundTableSpoolPopper(tableSpoolPopperSlots);

            var anchorRecursionCounter = tableSpoolPopperSlots.Last();
            var inc = Expression.Plus(Expression.Value(anchorRecursionCounter), Expression.Literal(1));
            var incRecursionSlot       = valueSlotFactory.CreateTemporary(typeof(int));
            var incRecursionDefinition = new BoundComputedValue(inc, incRecursionSlot);
            var incRecursion           = new BoundComputeRelation(tableSpoolPopper, ImmutableArray.Create(incRecursionDefinition));

            // Create recursive members

            var recursiveRewriter      = new CommonTableExpressionInstantiator(symbol);
            var recursiveMembers       = new List <BoundRelation>(symbol.RecursiveMembers.Length);
            var recursiveMemberOutputs = new List <ImmutableArray <ValueSlot> >(symbol.RecursiveMembers.Length);

            var anchorReferences = tableSpoolPopperSlots.RemoveAt(tableSpoolPopperSlots.Length - 1);

            foreach (var recursiveMember in symbol.RecursiveMembers)
            {
                var recursivePrototype       = recursiveMember.Relation;
                var mapping                  = CreateRecursiveMemberInstanceValueSlotMapping(symbol, anchorReferences, recursivePrototype);
                var recursiveInstance        = Instatiator.Instantiate(recursivePrototype, mapping);
                var recursiveRelation        = recursiveRewriter.RewriteRelation(recursiveInstance);
                var recursiveRelationOutputs = recursiveRelation.GetOutputValues().ToImmutableArray();
                recursiveMembers.Add(recursiveRelation);
                recursiveMemberOutputs.Add(recursiveRelationOutputs);
            }

            // Concatenate recursive members

            var recursiveConcatValues = Enumerable
                                        .Range(0, concatValueSlots.Length - 1)
                                        .Select(i =>
            {
                var slot = valueSlotFactory.CreateTemporary(concatValueSlots[i].Type);
                return(new BoundUnifiedValue(slot, recursiveMemberOutputs.Select(o => o[i])));
            })
                                        .ToImmutableArray();

            var hasSingleRecursiveMember = recursiveMembers.Count == 1;

            var recursiveConcat  = hasSingleRecursiveMember ? recursiveMembers.Single() : new BoundConcatenationRelation(recursiveMembers, recursiveConcatValues);
            var recursionOutputs = hasSingleRecursiveMember ? recursiveMemberOutputs.Single() : recursiveConcatValues.Select(u => u.ValueSlot).ToImmutableArray();

            // Create inner join

            var join                = new BoundJoinRelation(BoundJoinType.Inner, incRecursion, recursiveConcat, null, null, null);
            var joinOutputs         = recursionOutputs.Add(incRecursionSlot);
            var recursiveProjection = new BoundProjectRelation(join, joinOutputs);

            // Create assert

            var assertCondition = Expression.LessThan(Expression.Value(incRecursionSlot), Expression.Literal(100));
            var assert          = new BoundAssertRelation(recursiveProjection, assertCondition, Resources.MaximumRecursionLevelExceeded);

            // Create top level concat

            var concatValues = concatValueSlots.Select((v, i) =>
            {
                var slots = new[]
                {
                    initRecursionOutputs[i],
                    joinOutputs[i]
                };

                return(new BoundUnifiedValue(v, slots));
            });

            var concatInputs = new BoundRelation[] { initRecursion, assert };
            var concat       = new BoundConcatenationRelation(concatInputs, concatValues);

            var tableSpoolPusher = new BoundTableSpoolPusher(concat);

            return(new BoundProjectRelation(tableSpoolPusher, concatValueSlots.Take(concatValueSlots.Length - 1)));
        }
Exemple #21
0
 public JoinNode(BoundRelation relation)
 {
     Relation = relation;
 }
Exemple #22
0
        private static ImmutableDictionary <ValueSlot, ValueSlot> CreateRecursiveMemberInstanceValueSlotMapping(CommonTableExpressionSymbol symbol, ImmutableArray <ValueSlot> instanceSlots, BoundRelation relation)
        {
            var finder = new CommonTableExpressionInstanceFinder(symbol);

            finder.VisitRelation(relation);

            Debug.Assert(finder.Instance != null && finder.Instance.Table == symbol);
            Debug.Assert(instanceSlots.Length == finder.Instance.ColumnInstances.Length);

            return(instanceSlots.Zip(finder.Instance.ColumnInstances, (v, c) => new KeyValuePair <ValueSlot, ValueSlot>(c.ValueSlot, v))
                   .ToImmutableDictionary());
        }
Exemple #23
0
 private static BoundRelation WrapWithFilter(BoundRelation input, BoundExpression predicate)
 {
     return(predicate == null
         ? input
         : new BoundFilterRelation(input, predicate));
 }
        public static CardinalityEstimate Estimate(BoundRelation relation)
        {
            switch (relation.Kind)
            {
            case BoundNodeKind.TableRelation:
                return(EstimateTableRelation((BoundTableRelation)relation));

            case BoundNodeKind.DerivedTableRelation:
                return(EstimateDerivedTableRelation((BoundDerivedTableRelation)relation));

            case BoundNodeKind.JoinRelation:
                return(EstimateJoinRelation((BoundJoinRelation)relation));

            case BoundNodeKind.HashMatchRelation:
                return(EstimateHashMatchRelation((BoundHashMatchRelation)relation));

            case BoundNodeKind.ComputeRelation:
                return(EstimateComputeRelation((BoundComputeRelation)relation));

            case BoundNodeKind.FilterRelation:
                return(EstimateFilterRelation((BoundFilterRelation)relation));

            case BoundNodeKind.GroupByAndAggregationRelation:
                return(EstimateGroupByAndAggregationRelation((BoundGroupByAndAggregationRelation)relation));

            case BoundNodeKind.StreamAggregatesRelation:
                return(EstimateStreamAggregatesRelation((BoundStreamAggregatesRelation)relation));

            case BoundNodeKind.ConstantRelation:
                return(EstimateConstantRelation((BoundConstantRelation)relation));

            case BoundNodeKind.UnionRelation:
                return(EstimateUnionRelation((BoundUnionRelation)relation));

            case BoundNodeKind.ConcatenationRelation:
                return(EstimateConcatenationRelation((BoundConcatenationRelation)relation));

            case BoundNodeKind.IntersectOrExceptRelation:
                return(EstimateIntersectOrExceptRelation((BoundIntersectOrExceptRelation)relation));

            case BoundNodeKind.ProjectRelation:
                return(EstimateProjectRelation((BoundProjectRelation)relation));

            case BoundNodeKind.SortRelation:
                return(EstimateSortRelation((BoundSortRelation)relation));

            case BoundNodeKind.TopRelation:
                return(EstimateTopRelation((BoundTopRelation)relation));

            case BoundNodeKind.AssertRelation:
                return(EstimateAssertRelation((BoundAssertRelation)relation));

            case BoundNodeKind.TableSpoolPusher:
                return(EstimateTableSpoolPusher((BoundTableSpoolPusher)relation));

            case BoundNodeKind.TableSpoolPopper:
                return(EstimateTableSpoolPopper((BoundTableSpoolPopper)relation));

            default:
                throw ExceptionBuilder.UnexpectedValue(relation.Kind);
            }
        }