Esempio n. 1
0
        private void Map(List <SortKey> sortKeys)
        {
            VarVec varVec = this.m_command.CreateVarVec();
            bool   flag   = false;

            foreach (SortKey sortKey in sortKeys)
            {
                sortKey.Var = this.Map(sortKey.Var);
                if (varVec.IsSet(sortKey.Var))
                {
                    flag = true;
                }
                varVec.Set(sortKey.Var);
            }
            if (!flag)
            {
                return;
            }
            List <SortKey> sortKeyList = new List <SortKey>((IEnumerable <SortKey>)sortKeys);

            sortKeys.Clear();
            varVec.Clear();
            foreach (SortKey sortKey in sortKeyList)
            {
                if (!varVec.IsSet(sortKey.Var))
                {
                    sortKeys.Add(sortKey);
                }
                varVec.Set(sortKey.Var);
            }
        }
Esempio n. 2
0
        private void RemoveRedundantConstantKeys(VarVec keyVec, VarVec outputVec, System.Data.Entity.Core.Query.InternalTrees.Node varDefListNode)
        {
            List <System.Data.Entity.Core.Query.InternalTrees.Node> constantKeys = varDefListNode.Children.Where <System.Data.Entity.Core.Query.InternalTrees.Node>((Func <System.Data.Entity.Core.Query.InternalTrees.Node, bool>)(d =>
            {
                if (d.Op.OpType == OpType.VarDef)
                {
                    return(PlanCompilerUtil.IsConstantBaseOp(d.Child0.Op.OpType));
                }
                return(false);
            })).ToList <System.Data.Entity.Core.Query.InternalTrees.Node>();
            VarVec constantKeyVars = this.m_command.CreateVarVec(constantKeys.Select <System.Data.Entity.Core.Query.InternalTrees.Node, Var>((Func <System.Data.Entity.Core.Query.InternalTrees.Node, Var>)(d => ((VarDefOp)d.Op).Var)));

            constantKeyVars.Minus(this.m_referencedVars);
            keyVec.Minus(constantKeyVars);
            outputVec.Minus(constantKeyVars);
            varDefListNode.Children.RemoveAll((Predicate <System.Data.Entity.Core.Query.InternalTrees.Node>)(c =>
            {
                if (constantKeys.Contains(c))
                {
                    return(constantKeyVars.IsSet(((VarDefOp)c.Op).Var));
                }
                return(false);
            }));
            if (keyVec.Count != 0)
            {
                return;
            }
            System.Data.Entity.Core.Query.InternalTrees.Node node = constantKeys.First <System.Data.Entity.Core.Query.InternalTrees.Node>();
            Var var = ((VarDefOp)node.Op).Var;

            keyVec.Set(var);
            outputVec.Set(var);
            varDefListNode.Children.Add(node);
        }
        /// <summary>
        ///     Helper method for removing redundant constant keys from GroupByOp and DistictOp.
        ///     It only examines the keys defined in the given varDefListNode.
        ///     It removes all constant and null keys that are not referenced elsewhere,
        ///     but ensuring that at least one key is left.
        ///     It should not be called with empty keyVec.
        /// </summary>
        /// <param name="keyVec"> The keys </param>
        /// <param name="outputVec"> The var vec that needs to be updated along with the keys </param>
        /// <param name="varDefListNode"> Var def list node for the keys </param>
        private void RemoveRedundantConstantKeys(VarVec keyVec, VarVec outputVec, Node varDefListNode)
        {
            //Find all the keys that are nulls and constants
            var constantKeys = varDefListNode.Children.Where(
                d => d.Op.OpType == OpType.VarDef &&
                PlanCompilerUtil.IsConstantBaseOp(d.Child0.Op.OpType)).ToList();

            var constantKeyVars = m_command.CreateVarVec(constantKeys.Select(d => ((VarDefOp)d.Op).Var));

            //Get the list of unreferenced  constant keys
            constantKeyVars.Minus(m_referencedVars);

            //Remove the unreferenced constant keys
            keyVec.Minus(constantKeyVars);
            outputVec.Minus(constantKeyVars);

            varDefListNode.Children.RemoveAll(c => constantKeys.Contains(c) && constantKeyVars.IsSet(((VarDefOp)c.Op).Var));

            //If no keys are left add one.
            if (keyVec.Count == 0)
            {
                var keyNode = constantKeys.First();
                var keyVar  = ((VarDefOp)keyNode.Op).Var;
                keyVec.Set(keyVar);
                outputVec.Set(keyVar);
                varDefListNode.Children.Add(keyNode);
            }
        }
Esempio n. 4
0
        internal Table(Command command, TableMD tableMetadata, int tableId)
        {
            m_tableMetadata = tableMetadata;
            m_columns = Command.CreateVarList();
            m_keys = command.CreateVarVec();
            m_nonnullableColumns = command.CreateVarVec();
            m_tableId = tableId;

            var columnVarMap = new Dictionary<string, ColumnVar>();
            foreach (var c in tableMetadata.Columns)
            {
                var v = command.CreateColumnVar(this, c);
                columnVarMap[c.Name] = v;
                if (!c.IsNullable)
                {
                    m_nonnullableColumns.Set(v);
                }
            }

            foreach (var c in tableMetadata.Keys)
            {
                var v = columnVarMap[c.Name];
                m_keys.Set(v);
            }

            m_referencedColumns = command.CreateVarVec(m_columns);
        }
        private static bool ProcessApplyIntoScalarSubquery(
            RuleProcessingContext context,
            System.Data.Entity.Core.Query.InternalTrees.Node applyNode,
            out System.Data.Entity.Core.Query.InternalTrees.Node newNode)
        {
            Command          command           = context.Command;
            ExtendedNodeInfo extendedNodeInfo1 = command.GetExtendedNodeInfo(applyNode.Child1);
            OpType           opType            = applyNode.Op.OpType;

            if (!ApplyOpRules.CanRewriteApply(applyNode.Child1, extendedNodeInfo1, opType))
            {
                newNode = applyNode;
                return(false);
            }
            ExtendedNodeInfo extendedNodeInfo2 = command.GetExtendedNodeInfo(applyNode.Child0);
            Var    first  = extendedNodeInfo1.Definitions.First;
            VarVec varVec = command.CreateVarVec(extendedNodeInfo2.Definitions);
            TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context;

            transformationRulesContext.RemapSubtree(applyNode.Child1);
            ApplyOpRules.VarDefinitionRemapper.RemapSubtree(applyNode.Child1, command, first);
            System.Data.Entity.Core.Query.InternalTrees.Node node = command.CreateNode((Op)command.CreateElementOp(first.Type), applyNode.Child1);
            Var computedVar;

            System.Data.Entity.Core.Query.InternalTrees.Node varDefListNode = command.CreateVarDefListNode(node, out computedVar);
            varVec.Set(computedVar);
            newNode = command.CreateNode((Op)command.CreateProjectOp(varVec), applyNode.Child0, varDefListNode);
            transformationRulesContext.AddVarMapping(first, computedVar);
            return(true);
        }
Esempio n. 6
0
        private Node VisitCollectionAggregateFunction(FunctionOp op, Node n)
        {
            TypeUsage type   = (TypeUsage)null;
            Node      child0 = n.Child0;

            if (OpType.SoftCast == child0.Op.OpType)
            {
                type   = TypeHelpers.GetEdmType <CollectionType>(child0.Op.Type).TypeUsage;
                child0 = child0.Child0;
                while (OpType.SoftCast == child0.Op.OpType)
                {
                    child0 = child0.Child0;
                }
            }
            Node        node1       = this.BuildUnnest(child0);
            Var         column      = (node1.Op as UnnestOp).Table.Columns[0];
            AggregateOp aggregateOp = this.m_command.CreateAggregateOp(op.Function, false);
            Node        node2       = this.m_command.CreateNode((Op)this.m_command.CreateVarRefOp(column));

            if (type != null)
            {
                node2 = this.m_command.CreateNode((Op)this.m_command.CreateSoftCastOp(type), node2);
            }
            Node   node3   = this.m_command.CreateNode((Op)aggregateOp, node2);
            VarVec varVec1 = this.m_command.CreateVarVec();
            Node   node4   = this.m_command.CreateNode((Op)this.m_command.CreateVarDefListOp());
            VarVec varVec2 = this.m_command.CreateVarVec();
            Var    computedVar;
            Node   varDefListNode = this.m_command.CreateVarDefListNode(node3, out computedVar);

            varVec2.Set(computedVar);
            Node node5 = this.m_command.CreateNode((Op)this.m_command.CreateGroupByOp(varVec1, varVec2), node1, node4, varDefListNode);

            return(this.AddSubqueryToParentRelOp(computedVar, node5));
        }
Esempio n. 7
0
 private static VarVec CreateVarVec(params int[] bits)
 {
     var command = new Mock<Command>();
     var vec = new VarVec(command.Object);
     bits.Each(b =>
                   {
                       var v = CreateVar(b);
                       vec.Set(v);
                       command.Setup(m => m.GetVar(b)).Returns(v);
                   });
     return vec;
 }
        private void Map(List <InternalTrees.SortKey> sortKeys)
        {
            VarVec sortVars      = m_command.CreateVarVec();
            bool   hasDuplicates = false;

            //
            // Map each var in the sort list. Remapping may introduce duplicates, and
            // we should get rid of duplicates, since sql doesn't like them
            //
            foreach (InternalTrees.SortKey sk in sortKeys)
            {
                sk.Var = Map(sk.Var);
                if (sortVars.IsSet(sk.Var))
                {
                    hasDuplicates = true;
                }
                sortVars.Set(sk.Var);
            }

            //
            // Get rid of any duplicates
            //
            if (hasDuplicates)
            {
                List <InternalTrees.SortKey> newSortKeys = new List <SortKey>(sortKeys);
                sortKeys.Clear();
                sortVars.Clear();
                foreach (InternalTrees.SortKey sk in newSortKeys)
                {
                    if (!sortVars.IsSet(sk.Var))
                    {
                        sortKeys.Add(sk);
                    }
                    sortVars.Set(sk.Var);
                }
            }
        }
Esempio n. 9
0
            public override void Visit(VarRefOp op, Node n)
            {
                var referencedVar = op.Var;

                if (m_varVec.IsSet(referencedVar))
                {
                    if (m_usedVars.IsSet(referencedVar))
                    {
                        m_anyUsedMoreThenOnce = true;
                    }
                    else
                    {
                        m_usedVars.Set(referencedVar);
                    }
                }
            }
Esempio n. 10
0
        /// <summary>
        /// Converts a collection aggregate function count(X), where X is a collection into
        /// two parts. Part A is a groupby subquery that looks like
        ///    GroupBy(Unnest(X), empty, count(y))
        /// where "empty" describes the fact that the groupby has no keys, and y is an
        /// element var of the Unnest
        ///
        /// Part 2 is a VarRef that refers to the aggregate var for count(y) described above.
        ///
        /// Logically, we would replace the entire functionOp by element(GroupBy...). However,
        /// since we also want to translate element() into single-row-subqueries, we do this
        /// here as well.
        ///
        /// The function itself is replaced by the VarRef, and the GroupBy is added to the list
        /// of scalar subqueries for the current relOp node on the stack
        ///
        /// </summary>
        /// <param name="op">the functionOp for the collection agg</param>
        /// <param name="n">current subtree</param>
        /// <returns>the VarRef node that should replace the function</returns>
        private Node VisitCollectionAggregateFunction(FunctionOp op, Node n)
        {
            TypeUsage softCastType = null;
            Node      argNode      = n.Child0;

            if (OpType.SoftCast == argNode.Op.OpType)
            {
                softCastType = TypeHelpers.GetEdmType <CollectionType>(argNode.Op.Type).TypeUsage;
                argNode      = argNode.Child0;

                while (OpType.SoftCast == argNode.Op.OpType)
                {
                    argNode = argNode.Child0;
                }
            }

            Node     unnestNode      = BuildUnnest(argNode);
            UnnestOp unnestOp        = unnestNode.Op as UnnestOp;
            Var      unnestOutputVar = unnestOp.Table.Columns[0];

            AggregateOp aggregateOp      = m_command.CreateAggregateOp(op.Function, false);
            VarRefOp    unnestVarRefOp   = m_command.CreateVarRefOp(unnestOutputVar);
            Node        unnestVarRefNode = m_command.CreateNode(unnestVarRefOp);

            if (softCastType != null)
            {
                unnestVarRefNode = m_command.CreateNode(m_command.CreateSoftCastOp(softCastType), unnestVarRefNode);
            }
            Node aggExprNode = m_command.CreateNode(aggregateOp, unnestVarRefNode);

            VarVec keyVars           = m_command.CreateVarVec(); // empty keys
            Node   keyVarDefListNode = m_command.CreateNode(m_command.CreateVarDefListOp());

            VarVec gbyOutputVars = m_command.CreateVarVec();
            Var    aggVar;
            Node   aggVarDefListNode = m_command.CreateVarDefListNode(aggExprNode, out aggVar);

            gbyOutputVars.Set(aggVar);
            GroupByOp gbyOp           = m_command.CreateGroupByOp(keyVars, gbyOutputVars);
            Node      gbySubqueryNode = m_command.CreateNode(gbyOp, unnestNode, keyVarDefListNode, aggVarDefListNode);

            // "Move" this subquery to my parent relop
            Node ret = AddSubqueryToParentRelOp(aggVar, gbySubqueryNode);

            return(ret);
        }
Esempio n. 11
0
        // <summary>
        // Convert a CollectOp subtree (when used as the defining expression for a
        // VarDefOp) into a reasonable input to a NestOp.
        // </summary>
        // <remarks>
        // There are a couple of cases that we handle here:
        // (a) PhysicalProject(X) ==> X
        // (b) PhysicalProject(Sort(X)) ==> Sort(X)
        // </remarks>
        // <param name="physicalProjectNode"> the child of the CollectOp </param>
        // <param name="collectionVar"> the collectionVar being defined </param>
        // <param name="collectionInfoList"> where to append the new collectionInfo </param>
        // <param name="collectionNodes"> where to append the collectionNode </param>
        // <param name="externalReferences"> a bit vector of external references of the physicalProject </param>
        // <param name="collectionReferences"> a bit vector of collection vars </param>
        private void ConvertToNestOpInput(
            Node physicalProjectNode, Var collectionVar, List<CollectionInfo> collectionInfoList, List<Node> collectionNodes,
            VarVec externalReferences, VarVec collectionReferences)
        {
            // Keep track of any external references the physicalProjectOp has
            externalReferences.Or(Command.GetNodeInfo(physicalProjectNode).ExternalReferences);

            // Case: (a) PhysicalProject(X) ==> X
            var nestOpInput = physicalProjectNode.Child0;

            // Now build the collectionInfo for this input, including the flattened
            // list of vars, which is essentially the outputs from the physicalProject
            // with the sortKey vars that aren't already in the outputs we already 
            // have.
            var physicalProjectOp = (PhysicalProjectOp)physicalProjectNode.Op;
            var flattenedElementVarList = Command.CreateVarList(physicalProjectOp.Outputs);
            var flattenedElementVarVec = Command.CreateVarVec(flattenedElementVarList); // Use a VarVec to make the lookups faster
            List<SortKey> sortKeys = null;

            if (OpType.Sort
                == nestOpInput.Op.OpType)
            {
                // Case: (b) PhysicalProject(Sort(X)) ==> Sort(X)
                var sortOp = (SortOp)nestOpInput.Op;
                sortKeys = OpCopier.Copy(Command, sortOp.Keys);

                foreach (var sk in sortKeys)
                {
                    if (!flattenedElementVarVec.IsSet(sk.Var))
                    {
                        flattenedElementVarList.Add(sk.Var);
                        flattenedElementVarVec.Set(sk.Var);
                    }
                }
            }
            else
            {
                sortKeys = new List<SortKey>();
            }

            // Get the keys for the collection
            var keyVars = Command.GetExtendedNodeInfo(nestOpInput).Keys.KeyVars;

            //Check whether all key are projected
            var keyVarsClone = keyVars.Clone();
            keyVarsClone.Minus(flattenedElementVarVec);

            var keys = (keyVarsClone.IsEmpty) ? keyVars.Clone() : Command.CreateVarVec();

            // Create the collectionInfo
            var collectionInfo = Command.CreateCollectionInfo(
                collectionVar, physicalProjectOp.ColumnMap.Element, flattenedElementVarList, keys, sortKeys, null /*discriminatorValue*/);

            // Now update the collections we're tracking.
            collectionInfoList.Add(collectionInfo);
            collectionNodes.Add(nestOpInput);
            collectionReferences.Set(collectionVar);
        }
Esempio n. 12
0
 // <summary>
 // If we're going to eat the ProjectNode, then we at least need to make
 // sure we remap any vars it defines as varRefs, and ensure that any
 // references to them are switched.
 // </summary>
 private void EnsureReferencedVarsAreRemoved(List<Node> referencedVars, VarVec outputVars)
 {
     foreach (var chi in referencedVars)
     {
         var varDefOp = (VarDefOp)chi.Op;
         var defVar = varDefOp.Var;
         var refVar = ResolveVarReference(defVar);
         m_varRemapper.AddMapping(defVar, refVar);
         outputVars.Clear(defVar);
         outputVars.Set(refVar);
     }
 }
Esempio n. 13
0
        /// <summary>
        /// Comments from Murali:
        ///
        ///   There are several cases to consider here.
        ///
        ///   Case 0:
        ///     Let’s assume that K1 is the set of keys ({k1, k2, ..., kn}) for the
        ///     first input, and K2 ({l1, l2, …}) is the set of keys for the second
        ///     input.
        ///
        ///     The best case is when both K1 and K2 have the same cardinality (hopefully
        ///     greater than 0), and the keys are in the same locations (ie) the corresponding
        ///     positions in the select-list.  Even in this case, its not enough to take
        ///     the keys, and treat them as the keys of the union-all. What we’ll need to
        ///     do is to add a “branch” discriminator constant for each branch of the
        ///     union-all, and use this as the prefix for the keys.
        ///
        ///     For example, if I had:
        ///
        ///         Select c1, c2, c3... from ...
        ///         Union all
        ///         Select d1, d2, d3... from ...
        ///
        ///     And for the sake of argument, lets say that {c2} and {d2} are the keys of
        ///     each of the branches. What you’ll need to do is to translate this into
        ///
        ///         Select 0 as bd, c1, c2, c3... from ...
        ///         Union all
        ///         Select 1 as bd, d1, d2, d3... from ...
        ///
        ///     And then treat {bd, c2/d2} as the key of the union-all
        ///
        ///   Case 1:  (actually, a subcase of Case 0):
        ///     Now, if the keys don’t align, then we can simply take the union of the
        ///     corresponding positions, and make them all the keys (we would still need
        ///     the branch discriminator)
        ///
        ///   Case 2:
        ///     Finally, if you need to “pull” up keys from either of the branches, it is
        ///     possible that the branches get out of whack.  We will then need to push up
        ///     the keys (with nulls if the other branch doesn’t have the corresponding key)
        ///     into the union-all. (We still need the branch discriminator).
        ///
        /// Now, unfortunately, whenever we've got polymorphic entity types, we'll end up
        /// in case 2 way more often than we really want to, because when we're pulling up
        /// keys, we don't want to reason about a caseop (which is how polymorphic types
        /// wrap their key value).
        ///
        /// To simplify all of this, we:
        ///
        /// (1) Pulling up the keys for both branches of the UnionAll, and computing which
        ///     keys are in the outputs and which are missing from the outputs.
        ///
        /// (2) Accumulate all the missing keys.
        ///
        /// (3) Slap a projectOp around each branch, adding a branch discriminator
        ///     var and all the missing keys.  When keys are missing from a different
        ///     branch, we'll construct null ops for them on the other branches.  If
        ///     a branch already has a branch descriminator, we'll re-use it instead
        ///     of constructing a new one.  (Of course, if there aren't any keys to
        ///     add and it's already including the branch discriminator we won't
        ///     need the projectOp)
        ///
        /// </summary>
        /// <param name="op">the UnionAllOp</param>
        /// <param name="n">current subtree</param>
        public override void Visit(UnionAllOp op, Node n)
        {
#if DEBUG
            string input = Dump.ToXml(m_command, n);
#endif //DEBUG

            // Ensure we have keys pulled up on each branch of the union all.
            VisitChildren(n);

            // Create the setOp var we'll use to output the branch discriminator value; if
            // any of the branches are already surfacing a branchDiscriminator var to the
            // output of this operation then we won't need to use this but we construct it
            // early to simplify logic.
            Var outputBranchDiscriminatorVar = m_command.CreateSetOpVar(m_command.IntegerType);

            // Now ensure that we're outputting the key vars from this op as well.
            VarList  allKeyVarsMissingFromOutput = Command.CreateVarList();
            VarVec[] keyVarsMissingFromOutput    = new VarVec[n.Children.Count];

            for (int i = 0; i < n.Children.Count; i++)
            {
                Node             branchNode     = n.Children[i];
                ExtendedNodeInfo branchNodeInfo = m_command.GetExtendedNodeInfo(branchNode);

                // Identify keys that aren't in the output list of this operation. We
                // determine these by remapping the keys that are found through the node's
                // VarMap, which gives us the keys in the same "varspace" as the outputs
                // of the UnionAll, then we subtract out the outputs of this UnionAll op,
                // leaving things that are not in the output vars.  Of course, if they're
                // not in the output vars, then we didn't really remap.
                VarVec existingKeyVars = branchNodeInfo.Keys.KeyVars.Remap(op.VarMap[i]);

                keyVarsMissingFromOutput[i] = m_command.CreateVarVec(existingKeyVars);
                keyVarsMissingFromOutput[i].Minus(op.Outputs);

                // Special Case: if the branch is a UnionAll, it will already have it's
                // branch discriminator var added in the keys; we don't want to add that
                // a second time...
                if (OpType.UnionAll == branchNode.Op.OpType)
                {
                    UnionAllOp branchUnionAllOp = (UnionAllOp)branchNode.Op;

                    keyVarsMissingFromOutput[i].Clear(branchUnionAllOp.BranchDiscriminator);
                }

                allKeyVarsMissingFromOutput.AddRange(keyVarsMissingFromOutput[i]);
            }

            // Construct the setOp vars we're going to map to output.
            VarList allKeyVarsToAddToOutput = Command.CreateVarList();

            foreach (Var v in allKeyVarsMissingFromOutput)
            {
                Var newKeyVar = m_command.CreateSetOpVar(v.Type);
                allKeyVarsToAddToOutput.Add(newKeyVar);
            }

            // Now that we've identified all the keys we need to add, ensure that each branch
            // has both the branch discrimination var and the all the keys in them, even when
            // the keys are just going to null (which we construct, as needed)
            for (int i = 0; i < n.Children.Count; i++)
            {
                Node             branchNode     = n.Children[i];
                ExtendedNodeInfo branchNodeInfo = m_command.GetExtendedNodeInfo(branchNode);

                VarVec      branchOutputVars = m_command.CreateVarVec();
                List <Node> varDefNodes      = new List <Node>();

                // If the branch is a UnionAllOp that has a branch discriminator var then we can
                // use it, otherwise we'll construct a new integer constant with the next value
                // of the branch discriminator value from the command object.
                Var branchDiscriminatorVar;

                if (OpType.UnionAll == branchNode.Op.OpType && null != ((UnionAllOp)branchNode.Op).BranchDiscriminator)
                {
                    branchDiscriminatorVar = ((UnionAllOp)branchNode.Op).BranchDiscriminator;

                    // If the branch has a discriminator var, but we haven't added it to the
                    // varmap yet, then we do so now.
                    if (!op.VarMap[i].ContainsValue(branchDiscriminatorVar))
                    {
                        op.VarMap[i].Add(outputBranchDiscriminatorVar, branchDiscriminatorVar);
                        // We don't need to add this to the branch outputs, because it's already there,
                        // otherwise we wouln't have gotten here, yes?
                    }
                    else
                    {
                        // In this case, we're already outputting the branch discriminator var -- we'll
                        // just use it for both sides.  We should never have a case where only one of the
                        // two branches are outputting the branch discriminator var, because it can only
                        // be constructed in this method, and we wouldn't need it for any other purpose.
                        PlanCompiler.Assert(0 == i, "right branch has a discriminator var that the left branch doesn't have?");
                        VarMap reverseVarMap = op.VarMap[i].GetReverseMap();
                        outputBranchDiscriminatorVar = reverseVarMap[branchDiscriminatorVar];
                    }
                }
                else
                {
                    // Not a unionAll -- we have to add a BranchDiscriminator var.
                    varDefNodes.Add(
                        m_command.CreateVarDefNode(
                            m_command.CreateNode(
                                m_command.CreateConstantOp(m_command.IntegerType, m_command.NextBranchDiscriminatorValue)), out branchDiscriminatorVar));

                    branchOutputVars.Set(branchDiscriminatorVar);
                    op.VarMap[i].Add(outputBranchDiscriminatorVar, branchDiscriminatorVar);
                }

                // Append all the missing keys to the branch outputs.  If the missing key
                // is not from this branch then create a null.
                for (int j = 0; j < allKeyVarsMissingFromOutput.Count; j++)
                {
                    Var keyVar = allKeyVarsMissingFromOutput[j];

                    if (!keyVarsMissingFromOutput[i].IsSet(keyVar))
                    {
                        varDefNodes.Add(
                            m_command.CreateVarDefNode(
                                m_command.CreateNode(
                                    m_command.CreateNullOp(keyVar.Type)), out keyVar));

                        branchOutputVars.Set(keyVar);
                    }

                    // In all cases, we're adding a key to the output so we need to update the
                    // varmap.
                    op.VarMap[i].Add(allKeyVarsToAddToOutput[j], keyVar);
                }

                // If we got this far and didn't add anything to the branch, then we're done.
                // Otherwise we'll have to construct the new projectOp around the input branch
                // to add the stuff we've added.
                if (branchOutputVars.IsEmpty)
                {
                    // Actually, we're not quite done -- we need to update the key vars for the
                    // branch to include the branch discriminator var we
                    branchNodeInfo.Keys.KeyVars.Set(branchDiscriminatorVar);
                }
                else
                {
                    PlanCompiler.Assert(varDefNodes.Count != 0, "no new nodes?");

                    // Start by ensuring all the existing outputs from the branch are in the list.
                    foreach (Var v in op.VarMap[i].Values)
                    {
                        branchOutputVars.Set(v);
                    }

                    // Now construct a project op to project out everything we've added, and
                    // replace the branchNode with it in the flattened ladder.
                    n.Children[i] = m_command.CreateNode(m_command.CreateProjectOp(branchOutputVars),
                                                         branchNode,
                                                         m_command.CreateNode(m_command.CreateVarDefListOp(), varDefNodes));

                    // Finally, ensure that we update the Key info for the projectOp to include
                    // the original branch's keys, along with the branch discriminator var.
                    m_command.RecomputeNodeInfo(n.Children[i]);
                    ExtendedNodeInfo projectNodeInfo = m_command.GetExtendedNodeInfo(n.Children[i]);
                    projectNodeInfo.Keys.KeyVars.InitFrom(branchNodeInfo.Keys.KeyVars);
                    projectNodeInfo.Keys.KeyVars.Set(branchDiscriminatorVar);
                }
            }

            // All done with the branches, now it's time to update the UnionAll op to indicate
            // that we've got a branch discriminator var.
            n.Op = m_command.CreateUnionAllOp(op.VarMap[0], op.VarMap[1], outputBranchDiscriminatorVar);

            // Finally, the thing we've all been waiting for -- computing the keys.  We cheat here and let
            // nodeInfo do it so we don't have to duplicate the logic...
            m_command.RecomputeNodeInfo(n);

#if DEBUG
            input = input.Trim();
            string output = Dump.ToXml(m_command, n);
#endif //DEBUG
        }
 /// <summary>
 ///     Adds a reference to this Var
 /// </summary>
 /// <param name="v"> </param>
 private void AddReference(Var v)
 {
     m_referencedVars.Set(v);
 }
Esempio n. 15
0
        private static bool ProcessJoinOverProject(
            RuleProcessingContext context,
            System.Data.Entity.Core.Query.InternalTrees.Node joinNode,
            out System.Data.Entity.Core.Query.InternalTrees.Node newNode)
        {
            newNode = joinNode;
            TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context;
            Command command = transformationRulesContext.Command;

            System.Data.Entity.Core.Query.InternalTrees.Node node1 = joinNode.HasChild2 ? joinNode.Child2 : (System.Data.Entity.Core.Query.InternalTrees.Node)null;
            Dictionary <Var, int> varRefMap = new Dictionary <Var, int>();

            if (node1 != null && !transformationRulesContext.IsScalarOpTree(node1, varRefMap))
            {
                return(false);
            }
            VarVec varVec1 = command.CreateVarVec();
            List <System.Data.Entity.Core.Query.InternalTrees.Node> args = new List <System.Data.Entity.Core.Query.InternalTrees.Node>();

            if (joinNode.Op.OpType != OpType.LeftOuterJoin && joinNode.Child0.Op.OpType == OpType.Project && joinNode.Child1.Op.OpType == OpType.Project)
            {
                ProjectOp op1 = (ProjectOp)joinNode.Child0.Op;
                ProjectOp op2 = (ProjectOp)joinNode.Child1.Op;
                Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node> varMap1 = transformationRulesContext.GetVarMap(joinNode.Child0.Child1, varRefMap);
                Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node> varMap2 = transformationRulesContext.GetVarMap(joinNode.Child1.Child1, varRefMap);
                if (varMap1 == null || varMap2 == null)
                {
                    return(false);
                }
                System.Data.Entity.Core.Query.InternalTrees.Node node2;
                if (node1 != null)
                {
                    System.Data.Entity.Core.Query.InternalTrees.Node node3 = transformationRulesContext.ReMap(node1, varMap1);
                    System.Data.Entity.Core.Query.InternalTrees.Node node4 = transformationRulesContext.ReMap(node3, varMap2);
                    node2 = context.Command.CreateNode(joinNode.Op, joinNode.Child0.Child0, joinNode.Child1.Child0, node4);
                }
                else
                {
                    node2 = context.Command.CreateNode(joinNode.Op, joinNode.Child0.Child0, joinNode.Child1.Child0);
                }
                varVec1.InitFrom(op1.Outputs);
                foreach (Var output in op2.Outputs)
                {
                    varVec1.Set(output);
                }
                ProjectOp projectOp = command.CreateProjectOp(varVec1);
                args.AddRange((IEnumerable <System.Data.Entity.Core.Query.InternalTrees.Node>)joinNode.Child0.Child1.Children);
                args.AddRange((IEnumerable <System.Data.Entity.Core.Query.InternalTrees.Node>)joinNode.Child1.Child1.Children);
                System.Data.Entity.Core.Query.InternalTrees.Node node5 = command.CreateNode((Op)command.CreateVarDefListOp(), args);
                System.Data.Entity.Core.Query.InternalTrees.Node node6 = command.CreateNode((Op)projectOp, node2, node5);
                newNode = node6;
                return(true);
            }
            int index1;
            int index2;

            if (joinNode.Child0.Op.OpType == OpType.Project)
            {
                index1 = 0;
                index2 = 1;
            }
            else
            {
                System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(joinNode.Op.OpType != OpType.LeftOuterJoin, "unexpected non-LeftOuterJoin");
                index1 = 1;
                index2 = 0;
            }
            System.Data.Entity.Core.Query.InternalTrees.Node child = joinNode.Children[index1];
            ProjectOp op = child.Op as ProjectOp;
            Dictionary <Var, System.Data.Entity.Core.Query.InternalTrees.Node> varMap = transformationRulesContext.GetVarMap(child.Child1, varRefMap);

            if (varMap == null)
            {
                return(false);
            }
            ExtendedNodeInfo extendedNodeInfo = command.GetExtendedNodeInfo(joinNode.Children[index2]);
            VarVec           varVec2          = command.CreateVarVec(op.Outputs);

            varVec2.Or(extendedNodeInfo.Definitions);
            op.Outputs.InitFrom(varVec2);
            if (node1 != null)
            {
                System.Data.Entity.Core.Query.InternalTrees.Node node2 = transformationRulesContext.ReMap(node1, varMap);
                joinNode.Child2 = node2;
            }
            joinNode.Children[index1] = child.Child0;
            context.Command.RecomputeNodeInfo(joinNode);
            newNode = context.Command.CreateNode((Op)op, joinNode, child.Child1);
            return(true);
        }
Esempio n. 16
0
        public override void Visit(UnionAllOp op, System.Data.Entity.Core.Query.InternalTrees.Node n)
        {
            this.VisitChildren(n);
            Var     var1     = (Var)this.m_command.CreateSetOpVar(this.m_command.IntegerType);
            VarList varList1 = Command.CreateVarList();

            VarVec[] varVecArray = new VarVec[n.Children.Count];
            for (int index = 0; index < n.Children.Count; ++index)
            {
                System.Data.Entity.Core.Query.InternalTrees.Node child = n.Children[index];
                VarVec v = this.m_command.GetExtendedNodeInfo(child).Keys.KeyVars.Remap((Dictionary <Var, Var>)op.VarMap[index]);
                varVecArray[index] = this.m_command.CreateVarVec(v);
                varVecArray[index].Minus(op.Outputs);
                if (OpType.UnionAll == child.Op.OpType)
                {
                    UnionAllOp op1 = (UnionAllOp)child.Op;
                    varVecArray[index].Clear(op1.BranchDiscriminator);
                }
                varList1.AddRange((IEnumerable <Var>)varVecArray[index]);
            }
            VarList varList2 = Command.CreateVarList();

            foreach (Var var2 in (List <Var>)varList1)
            {
                Var setOpVar = (Var)this.m_command.CreateSetOpVar(var2.Type);
                varList2.Add(setOpVar);
            }
            for (int index1 = 0; index1 < n.Children.Count; ++index1)
            {
                System.Data.Entity.Core.Query.InternalTrees.Node child = n.Children[index1];
                ExtendedNodeInfo extendedNodeInfo1 = this.m_command.GetExtendedNodeInfo(child);
                VarVec           varVec            = this.m_command.CreateVarVec();
                List <System.Data.Entity.Core.Query.InternalTrees.Node> args = new List <System.Data.Entity.Core.Query.InternalTrees.Node>();
                Var computedVar1;
                if (OpType.UnionAll == child.Op.OpType && ((UnionAllOp)child.Op).BranchDiscriminator != null)
                {
                    computedVar1 = ((UnionAllOp)child.Op).BranchDiscriminator;
                    if (!op.VarMap[index1].ContainsValue(computedVar1))
                    {
                        op.VarMap[index1].Add(var1, computedVar1);
                    }
                    else
                    {
                        System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(0 == index1, "right branch has a discriminator var that the left branch doesn't have?");
                        var1 = op.VarMap[index1].GetReverseMap()[computedVar1];
                    }
                }
                else
                {
                    args.Add(this.m_command.CreateVarDefNode(this.m_command.CreateNode((Op)this.m_command.CreateConstantOp(this.m_command.IntegerType, (object)this.m_command.NextBranchDiscriminatorValue)), out computedVar1));
                    varVec.Set(computedVar1);
                    op.VarMap[index1].Add(var1, computedVar1);
                }
                for (int index2 = 0; index2 < varList1.Count; ++index2)
                {
                    Var computedVar2 = varList1[index2];
                    if (!varVecArray[index1].IsSet(computedVar2))
                    {
                        args.Add(this.m_command.CreateVarDefNode(this.m_command.CreateNode((Op)this.m_command.CreateNullOp(computedVar2.Type)), out computedVar2));
                        varVec.Set(computedVar2);
                    }
                    op.VarMap[index1].Add(varList2[index2], computedVar2);
                }
                if (varVec.IsEmpty)
                {
                    extendedNodeInfo1.Keys.KeyVars.Set(computedVar1);
                }
                else
                {
                    System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Assert(args.Count != 0, "no new nodes?");
                    foreach (Var v in op.VarMap[index1].Values)
                    {
                        varVec.Set(v);
                    }
                    n.Children[index1] = this.m_command.CreateNode((Op)this.m_command.CreateProjectOp(varVec), child, this.m_command.CreateNode((Op)this.m_command.CreateVarDefListOp(), args));
                    this.m_command.RecomputeNodeInfo(n.Children[index1]);
                    ExtendedNodeInfo extendedNodeInfo2 = this.m_command.GetExtendedNodeInfo(n.Children[index1]);
                    extendedNodeInfo2.Keys.KeyVars.InitFrom(extendedNodeInfo1.Keys.KeyVars);
                    extendedNodeInfo2.Keys.KeyVars.Set(computedVar1);
                }
            }
            n.Op = (Op)this.m_command.CreateUnionAllOp(op.VarMap[0], op.VarMap[1], var1);
            this.m_command.RecomputeNodeInfo(n);
        }