Пример #1
0
 /// <summary>
 /// Pull up keys (if possible) for the given node
 /// </summary>
 /// <param name="node">node to pull up keys for</param>
 /// <returns>Keys for the node</returns>
 internal KeyVec GetKeys(Node node)
 {
     ExtendedNodeInfo nodeInfo = node.GetExtendedNodeInfo(m_command);
     if (nodeInfo.Keys.NoKeys)
     {
         VisitNode(node);
     }
     return nodeInfo.Keys;
 }
Пример #2
0
        private Node ProjectOpCase1(Node projectNode)
        {
#if DEBUG
            var input = Dump.ToXml(projectNode);
#endif
            //DEBUG

            var op = (ProjectOp)projectNode.Op;

            // Check to see if any of the computed Vars are in fact NestOps, and
            // construct a collection column map for them.
            var collectionInfoList = new List<CollectionInfo>();
            var newChildren = new List<Node>();
            var collectionNodes = new List<Node>();
            var externalReferences = Command.CreateVarVec();
            var collectionReferences = Command.CreateVarVec();
            var definedVars = new List<Node>();
            var referencedVars = new List<Node>();

            foreach (var chi in projectNode.Child1.Children)
            {
                var varDefOp = (VarDefOp)chi.Op;
                var definingExprNode = chi.Child0;

                if (OpType.Collect
                    == definingExprNode.Op.OpType)
                {
                    PlanCompiler.Assert(definingExprNode.HasChild0, "collect without input?");
                    PlanCompiler.Assert(OpType.PhysicalProject == definingExprNode.Child0.Op.OpType, "collect without physicalProject?");
                    var physicalProjectNode = definingExprNode.Child0;

                    // Update collection var->defining node map;
                    m_definingNodeMap.Add(varDefOp.Var, physicalProjectNode);

                    ConvertToNestOpInput(
                        physicalProjectNode, varDefOp.Var, collectionInfoList, collectionNodes, externalReferences, collectionReferences);
                }
                else if (OpType.VarRef
                         == definingExprNode.Op.OpType)
                {
                    var refVar = ((VarRefOp)definingExprNode.Op).Var;
                    Node physicalProjectNode;

                    if (m_definingNodeMap.TryGetValue(refVar, out physicalProjectNode))
                    {
                        physicalProjectNode = CopyCollectionVarDefinition(physicalProjectNode);
                        //SQLBUDT #602888: We need to track the copy too, in case we need to reuse it
                        m_definingNodeMap.Add(varDefOp.Var, physicalProjectNode);
                        ConvertToNestOpInput(
                            physicalProjectNode, varDefOp.Var, collectionInfoList, collectionNodes, externalReferences, collectionReferences);
                    }
                    else
                    {
                        referencedVars.Add(chi);
                        newChildren.Add(chi);
                    }
                }
                else
                {
                    definedVars.Add(chi);
                    newChildren.Add(chi);
                }
            }

            // If we haven't identified a set of collection nodes, then we're done.
            if (0 == collectionNodes.Count)
            {
                return projectNode;
            }

            // OK, we found something. We have some heavy lifting to perform.

            // Then we need to build up a MultiStreamNestOp above the ProjectOp and the
            // new collection nodes to get what we really need.
            // pretend that the keys included everything from the new projectOp
            var outputVars = Command.CreateVarVec(op.Outputs);

            // First we need to modify this physicalProjectNode to leave out the collection
            // Vars that we've just seen.
            var newProjectVars = Command.CreateVarVec(op.Outputs);
            newProjectVars.Minus(collectionReferences);

            // If there are any external references from any of the collections, add
            // those to the projectOp explicitly. This must be ok because the projectOp
            // could not have had any left-correlation
            newProjectVars.Or(externalReferences);

            // Create the new projectOp, and hook it into this one.  The new projectOp
            // no longer references the collections in it's children; of course we only
            // construct a new projectOp if it actually projects out some Vars.  
            if (!newProjectVars.IsEmpty)
            {
                if (IsNestOpNode(projectNode.Child0))
                {
                    // If the input is a nest node, we need to figure out what to do with the
                    // rest of the in the VarDefList; we can't just pitch them, but we also 
                    // really want to have the input be a nestop.
                    //
                    // What we do is essentially push any non-collection VarDef�s down under 
                    // the driving node of the MSN:
                    //
                    //      Project[Z,Y,W](Msn(X,Y),VarDef(Z=blah),VarDef(W=Collect(etc)) ==> MSN(MSN(Project[Z](X,VarDef(Z=blah)),Y),W)
                    //
                    // An optimization, of course being to not push anything down when there
                    // aren't any extra vars defined.

                    if (definedVars.Count == 0
                        && referencedVars.Count == 0)
                    {
                        // We'll just pick the NestNode; we expect MergeNestedNestOps to merge
                        // it into what we're about to generate later.
                        projectNode = projectNode.Child0;
                        EnsureReferencedVarsAreRemoved(referencedVars, outputVars);
                    }
                    else
                    {
                        var nestedNestOp = (NestBaseOp)projectNode.Child0.Op;

                        // Build the new ProjectOp to be used as input to the new nestedNestOp; 
                        // it's input is the input to the current nestedNestOp and a new 
                        // VarDefList with only the vars that were defined on the top level 
                        // ProjectOp.
                        var newNestedProjectNodeInputs = new List<Node>();
                        newNestedProjectNodeInputs.Add(projectNode.Child0.Child0);
                        referencedVars.AddRange(definedVars);
                        newNestedProjectNodeInputs.Add(Command.CreateNode(Command.CreateVarDefListOp(), referencedVars));

                        var newNestedProjectOutputs = Command.CreateVarVec(nestedNestOp.Outputs);

                        // SQLBUDT #508722:  We need to remove the collection vars, 
                        //  these are not produced by the project
                        foreach (var ci in nestedNestOp.CollectionInfo)
                        {
                            newNestedProjectOutputs.Clear(ci.CollectionVar);
                        }

                        foreach (var varDefNode in referencedVars)
                        {
                            newNestedProjectOutputs.Set(((VarDefOp)varDefNode.Op).Var);
                        }

                        var newNestedProjectNode = Command.CreateNode(
                            Command.CreateProjectOp(newNestedProjectOutputs), newNestedProjectNodeInputs);

                        // Now build the new nestedNestedNestOp, with the new nestedProjectOp
                        // as it's input; we have to update the outputs of the NestOp to include
                        // the vars we pushed down.
                        var newNestedNestOutputs = Command.CreateVarVec(newNestedProjectOutputs);
                        newNestedNestOutputs.Or(nestedNestOp.Outputs);

                        var newNestedNestOp = Command.CreateMultiStreamNestOp(
                            nestedNestOp.PrefixSortKeys,
                            newNestedNestOutputs,
                            nestedNestOp.CollectionInfo);

                        var newNestedNestNodeInputs = new List<Node>();
                        newNestedNestNodeInputs.Add(newNestedProjectNode);
                        for (var j = 1; j < projectNode.Child0.Children.Count; j++)
                        {
                            newNestedNestNodeInputs.Add(projectNode.Child0.Children[j]);
                        }
                        projectNode = Command.CreateNode(newNestedNestOp, newNestedNestNodeInputs);
                        // We don't need to remove or remap referenced vars here because
                        // we're including them on the node we create; they won't become
                        // invalid.
                    }
                }
                else
                {
                    var newProjectOp = Command.CreateProjectOp(newProjectVars);
                    projectNode.Child1 = Command.CreateNode(projectNode.Child1.Op, newChildren);
                    projectNode.Op = newProjectOp;
                    EnsureReferencedVarsAreRemapped(referencedVars);
                }
            }
            else
            {
                projectNode = projectNode.Child0;
                EnsureReferencedVarsAreRemoved(referencedVars, outputVars);
            }

            // We need to make sure that we project out any external references to the driving
            // node that the nested collections have, or we're going to end up with unresolvable
            // vars when we pull them up over the current driving node.  Of course, we only 
            // want the references that are actually ON the driving node.
            externalReferences.And(projectNode.GetExtendedNodeInfo(Command).Definitions);
            outputVars.Or(externalReferences);

            // There are currently no prefix sortkeys. The processing for a SortOp may later
            // introduce some prefix sortkeys, but there aren't any now.
            var nestOp = Command.CreateMultiStreamNestOp(new List<SortKey>(), outputVars, collectionInfoList);

            // Insert the current node at the head of the the list of collections
            collectionNodes.Insert(0, projectNode);
            var nestNode = Command.CreateNode(nestOp, collectionNodes);

            // Finally, recompute node info
            Command.RecomputeNodeInfo(projectNode);
            Command.RecomputeNodeInfo(nestNode);

#if DEBUG
            var size = input.Length; // GC.KeepAlive makes FxCop Grumpy.
            var output = Dump.ToXml(nestNode);
#endif
            //DEBUG
            return nestNode;
        }
Пример #3
0
 /// <summary>
 /// Get extended node information for a RelOpNode
 /// </summary>
 /// <param name="n">the node</param>
 /// <returns>extended node info for this node</returns>
 internal ExtendedNodeInfo GetExtendedNodeInfo(Node n)
 {
     return n.GetExtendedNodeInfo(this);
 }