protected override BoundRelation RewriteJoinRelation(BoundJoinRelation node)
        {
            node = (BoundJoinRelation)base.RewriteJoinRelation(node);

            var needsRewriting = NeedsRewriting(node);

            if (!needsRewriting)
            {
                return(node);
            }

            var node1 = (BoundJoinRelation)Instatiator.Instantiate(node);
            var node2 = (BoundJoinRelation)Instatiator.Instantiate(node);

            var leftOuterJoin    = node1.Update(BoundJoinType.LeftOuter, node1.Left, node1.Right, node1.Condition, null, null);
            var leftAntiSemiJoin = node1.Update(BoundJoinType.LeftAntiSemi, node2.Right, node2.Left, node2.Condition, null, null);

            var computedValueSlots = node.Left.GetOutputValues().Select(v => v.Duplicate()).ToImmutableArray();
            var computedValues     = computedValueSlots.Select(v => new BoundComputedValue(Expression.Null(), v));
            var compute            = new BoundComputeRelation(leftAntiSemiJoin, computedValues);
            var project            = new BoundProjectRelation(compute, computedValueSlots.Concat(leftAntiSemiJoin.GetOutputValues()));

            var concatValueSlots = node.GetOutputValues().ToImmutableArray();
            var firstOutputs     = leftOuterJoin.GetOutputValues().ToImmutableArray();
            var secondOutputs    = project.GetOutputValues().ToImmutableArray();
            var unifiedValues    = new BoundUnifiedValue[concatValueSlots.Length];

            for (var i = 0; i < unifiedValues.Length; i++)
            {
                unifiedValues[i] = new BoundUnifiedValue(concatValueSlots[i], new[] { firstOutputs[i], secondOutputs[i] });
            }

            return(new BoundConcatenationRelation(new BoundRelation[] { leftOuterJoin, project }, unifiedValues));
        }
Пример #2
0
        private BoundRelation PushOverCompute(BoundFilterRelation node, BoundComputeRelation input)
        {
            BoundExpression remainder = null;
            BoundExpression pushed    = null;

            foreach (var conjunction in Expression.SplitConjunctions(node.Condition))
            {
                if (conjunction.DependsOnAny(input.GetDefinedValues()))
                {
                    remainder = Expression.And(remainder, conjunction);
                }
                else
                {
                    pushed = Expression.And(pushed, conjunction);
                }
            }

            var newInputInput = pushed == null
                ? input.Input
                : new BoundFilterRelation(input.Input, pushed);

            var newInput = RewriteRelation(input.Update(newInputInput, input.DefinedValues));

            var newNode = remainder == null
                ? newInput
                : new BoundFilterRelation(newInput, remainder);

            return(newNode);
        }
Пример #3
0
        protected override BoundRelation RewriteComputeRelation(BoundComputeRelation node)
        {
            var input           = RewriteRelation(node.Input);
            var computedValues  = RewriteComputedValues(node.DefinedValues);
            var inputWithProbes = RewriteInputWithSubqueries(input);

            return(node.Update(inputWithProbes, computedValues));
        }
Пример #4
0
        private Iterator BuildCompute(BoundComputeRelation relation)
        {
            var input        = BuildRelation(relation.Input);
            var allocation   = BuildRowBufferAllocation(relation.Input, input.RowBuffer);
            var definedValue = relation.DefinedValues
                               .Select(dv => BuildFunction(dv.Expression, allocation))
                               .ToImmutableArray();

            return(new ComputeScalarIterator(input, definedValue));
        }
Пример #5
0
        private static BoundQuery CreateBoundQuery(BoundExpression expression)
        {
            var factory          = new ValueSlotFactory();
            var valueSlot        = new ValueSlot(factory, @"result", 0, expression.Type);
            var computedValue    = new BoundComputedValue(expression, valueSlot);
            var constantRelation = new BoundConstantRelation();
            var computeRelation  = new BoundComputeRelation(constantRelation, new[] { computedValue });
            var projectRelation  = new BoundProjectRelation(computeRelation, new [] { valueSlot });
            var columnSymbol     = new QueryColumnInstanceSymbol(valueSlot.Name, valueSlot);

            return(new BoundQuery(projectRelation, new[] { columnSymbol }));
        }
Пример #6
0
        private static ShowPlanNode BuildCompute(BoundComputeRelation node)
        {
            var properties = Enumerable.Empty <KeyValuePair <string, string> >();
            var input      = new[] { Build(node.Input) };
            var aggregates = from d in node.DefinedValues
                             let dName = d.ValueSlot.Name
                                         let dProperties = Enumerable.Empty <KeyValuePair <string, string> >()
                                                           let dChildren = new[] { Build(d.Expression) }
            select new ShowPlanNode(dName, dProperties, dChildren);
            var children = input.Concat(aggregates);

            return(new ShowPlanNode(@"Compute", properties, children));
        }
Пример #7
0
        protected override BoundRelation RewriteComputeRelation(BoundComputeRelation node)
        {
            var newInput = RewriteRelation(node.Input);

            if (newInput is BoundFilterRelation filter)
            {
                node = node.Update(filter.Input, node.DefinedValues);
                return(filter.WithInput(node));
            }
            else
            {
                return(node.WithInput(newInput));
            }
        }
Пример #8
0
        protected override BoundRelation RewriteComputeRelation(BoundComputeRelation node)
        {
            var definedValues = RemoveUnusedSlots(node.DefinedValues, d => d.ValueSlot);

            node = node.Update(node.Input, definedValues);

            _recorder.Record(definedValues);

            if (!definedValues.Any())
            {
                return(RewriteRelation(node.Input));
            }

            return(base.RewriteComputeRelation(node));
        }
Пример #9
0
        private static Func <object> CreateTrivialExpression(BoundComputeRelation computeRelation)
        {
            var computedValue = computeRelation.DefinedValues.First();

            return(ExpressionBuilder.BuildFunction(computedValue.Expression));
        }
Пример #10
0
 private static CardinalityEstimate EstimateComputeRelation(BoundComputeRelation relation)
 {
     return(Estimate(relation.Input));
 }
Пример #11
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)));
        }