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));
        }
Exemplo n.º 2
0
        private BoundRelation InstantiateCommonTableExpression(ImmutableArray <ValueSlot> outputValues, CommonTableExpressionSymbol symbol)
        {
            var prototype             = symbol.Anchor.Relation;
            var prototypeOutputValues = prototype.GetOutputValues();
            var mapping = outputValues.Zip(prototypeOutputValues, (v, k) => new KeyValuePair <ValueSlot, ValueSlot>(k, v));

            var instantiatedRelation = Instatiator.Instantiate(prototype, mapping);

            return(RewriteRelation(instantiatedRelation));
        }
Exemplo n.º 3
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)));
        }