示例#1
0
 internal static Node Copy(Command cmd, Node n, out VarMap varMap)
 {
     var oc = new OpCopier(cmd);
     var newNode = oc.CopyNode(n);
     varMap = oc.m_varMap;
     return newNode;
 }
 /// <summary>
 /// Equivalent to OpCopier.Copy, only in addition it keeps track of the defining subtrees
 /// of collection vars defined in the subtree rooted at the copy of the input node n.
 /// </summary>
 /// <param name="cmd"></param>
 /// <param name="n"></param>
 /// <param name="varMap"></param>
 /// <param name="newCollectionVarDefinitions"></param>
 /// <returns></returns>
 internal static Node Copy(Command cmd, Node n, out VarMap varMap, out Dictionary<Var, Node> newCollectionVarDefinitions)
 {
     var oc = new OpCopierTrackingCollectionVars(cmd);
     var newNode = oc.CopyNode(n);
     varMap = oc.m_varMap;
     newCollectionVarDefinitions = oc.m_newCollectionVarDefinitions;
     return newNode;
 }
示例#3
0
 internal SetOp(OpType opType, VarVec outputs, VarMap left, VarMap right)
     : this(opType)
 {
     m_varMap = new VarMap[2];
     m_varMap[0] = left;
     m_varMap[1] = right;
     m_outputVars = outputs;
 }
        private Node FixupSetOpChild(Node setOpChild, VarMap varMap, List<ComputedVar> newComputedVars)
        {
            PlanCompiler.Assert(null != setOpChild, "null setOpChild?");
            PlanCompiler.Assert(null != varMap, "null varMap?");
            PlanCompiler.Assert(null != newComputedVars, "null newComputedVars?");

            // Walk through the list of Vars that have no inner analog, and create 
            // a computed Var for each of them
            var newVarSet = m_command.CreateVarVec();
            foreach (var kv in varMap)
            {
                newVarSet.Set(kv.Value);
            }

            var varDefOpNodes = new List<Node>();
            foreach (Var v in newComputedVars)
            {
                var varDefOp = m_command.CreateVarDefOp(v);
                var varDefOpNode = m_command.CreateNode(varDefOp, CreateNullConstantNode(v.Type));
                varDefOpNodes.Add(varDefOpNode);
            }
            var varDefListNode = m_command.CreateNode(m_command.CreateVarDefListOp(), varDefOpNodes);
            var projectOp = m_command.CreateProjectOp(newVarSet);
            var projectNode = m_command.CreateNode(projectOp, setOpChild, varDefListNode);
            return projectNode;
        }
示例#5
0
 /// <summary>
 /// Creates a new ExceptOp
 /// </summary>
 /// <param name="leftMap">Mappings from the Output Vars to the Vars produced by the left argument</param>
 /// <param name="rightMap">Mappings from the Output Vars to the Vars produced by the right argument</param>
 /// <returns>An ExceptOp that references the specified left and right Vars</returns>
 internal ExceptOp CreateExceptOp(VarMap leftMap, VarMap rightMap)
 {
     Debug.Assert(leftMap.Count == rightMap.Count, "VarMap count mismatch");
     VarVec vec = this.CreateVarVec();
     foreach (Var v in leftMap.Keys)
     {
         vec.Set(v);
     }
     return new ExceptOp(vec, leftMap, rightMap);
 }
示例#6
0
 /// <summary>
 /// Creates a new UnionAllOp, with a branch descriminator.
 /// </summary>
 /// <param name="leftMap">Mappings from the Output Vars to the Vars produced by the left argument</param>
 /// <param name="rightMap">Mappings from the Output Vars to the Vars produced by the right argument</param>
 /// <param name="branchDiscriminator">Var that contains the branch discrimination value (may be null until key pullup occurs)</param>
 /// <returns>A UnionAllOp that references the specified left and right Vars</returns>
 internal UnionAllOp CreateUnionAllOp(VarMap leftMap, VarMap rightMap, Var branchDiscriminator) 
 {
     Debug.Assert(leftMap.Count == rightMap.Count, "VarMap count mismatch");
     VarVec vec = this.CreateVarVec();
     foreach (Var v in leftMap.Keys)
     {
         vec.Set(v);
     }
     return new UnionAllOp(vec, leftMap, rightMap, branchDiscriminator);
 }
示例#7
0
 /// <summary>
 /// Creates a new UnionAllOp
 /// </summary>
 /// <param name="leftMap">Mappings from the Output Vars to the Vars produced by the left argument</param>
 /// <param name="rightMap">Mappings from the Output Vars to the Vars produced by the right argument</param>
 /// <returns>A UnionAllOp that references the specified left and right Vars</returns>
 internal UnionAllOp CreateUnionAllOp(VarMap leftMap, VarMap rightMap)
 {
     return CreateUnionAllOp(leftMap, rightMap, null);
 }
 public ChainedMap(VarMap <K, V> next, Map <K, V> map)
 {
     _next = next;
     _map  = map;
 }
示例#9
0
 // <summary>
 // Constructor. Allows for cloning of nodes across commands
 // </summary>
 // <param name="destCommand"> The Command to which Nodes to be cloned must belong </param>
 // <param name="sourceCommand"> The Command to which cloned Nodes will belong </param>
 private OpCopier(Command destCommand, Command sourceCommand)
 {
     m_srcCmd = sourceCommand;
     m_destCmd = destCommand;
     m_varMap = new VarMap();
 }
示例#10
0
 private void Map(VarMap varMap)
 {
     var newVarMap = new VarMap();
     foreach (var kv in varMap)
     {
         var newVar = Map(kv.Value);
         newVarMap.Add(kv.Key, newVar);
     }
     varMap.Clear();
     foreach (var kv in newVarMap)
     {
         varMap.Add(kv.Key, kv.Value);
     }
 }
示例#11
0
 private void Map(VarMap varMap)
 {
     VarMap newVarMap = new VarMap();
     foreach (KeyValuePair<Var, Var> kv in varMap)
     {
         Var newVar = Map(kv.Value);
         newVarMap.Add(kv.Key, newVar);
     }
     varMap.Clear();
     foreach (KeyValuePair<Var, Var> kv in newVarMap)
     {
         varMap.Add(kv.Key, kv.Value);
     }
 }
示例#12
0
        // <summary>
        // Builds out a UNION-ALL ladder from a sequence of node,var pairs.
        // Assumption: Each node produces exactly one Var
        // If the input sequence has zero elements, we return null
        // If the input sequence has one element, we return that single element
        // Otherwise, we build out a UnionAll ladder from each of the inputs. If the input sequence was {A,B,C,D},
        // we build up a union-all ladder that looks like
        // (((A UA B) UA C) UA D)
        // </summary>
        // <param name="inputNodes"> list of input nodes - one for each branch </param>
        // <param name="inputVars"> list of input vars - N for each branch </param>
        // <param name="resultNode"> the resulting union-all subtree </param>
        // <param name="resultVars"> the output vars from the union-all subtree </param>
        internal virtual void BuildUnionAllLadder(
            IList<Node> inputNodes, IList<Var> inputVars,
            out Node resultNode, out IList<Var> resultVars)
        {
            if (inputNodes.Count == 0)
            {
                resultNode = null;
                resultVars = null;
                return;
            }

            var varPerNode = inputVars.Count / inputNodes.Count;
            Debug.Assert(
                (inputVars.Count % inputNodes.Count == 0) && (varPerNode >= 1),
                "Inconsistent nodes/vars count:" + inputNodes.Count + "," + inputVars.Count);

            if (inputNodes.Count == 1)
            {
                resultNode = inputNodes[0];
                resultVars = inputVars;
                return;
            }

            var unionAllVars = new List<Var>();

            var unionAllNode = inputNodes[0];
            for (var j = 0; j < varPerNode; j++)
            {
                unionAllVars.Add(inputVars[j]);
            }

            for (var i = 1; i < inputNodes.Count; i++)
            {
                var leftVarMap = new VarMap();
                var rightVarMap = new VarMap();
                var setOpVars = new List<Var>();
                for (var j = 0; j < varPerNode; j++)
                {
                    var newVar = CreateSetOpVar(unionAllVars[j].Type);
                    setOpVars.Add(newVar);
                    leftVarMap.Add(newVar, unionAllVars[j]);
                    rightVarMap.Add(newVar, inputVars[i * varPerNode + j]);
                }
                Op unionAllOp = CreateUnionAllOp(leftVarMap, rightVarMap);
                unionAllNode = CreateNode(unionAllOp, unionAllNode, inputNodes[i]);
                unionAllVars = setOpVars;
            }

            resultNode = unionAllNode;
            resultVars = unionAllVars;
        }
示例#13
0
 // <summary>
 // Creates a new IntersectOp
 // </summary>
 // <param name="leftMap"> Mappings from the Output Vars to the Vars produced by the left argument </param>
 // <param name="rightMap"> Mappings from the Output Vars to the Vars produced by the right argument </param>
 // <returns> An IntersectOp that references the specified left and right Vars </returns>
 internal virtual IntersectOp CreateIntersectOp(VarMap leftMap, VarMap rightMap)
 {
     Debug.Assert(leftMap.Count == rightMap.Count, "VarMap count mismatch");
     var vec = CreateVarVec();
     foreach (var v in leftMap.Keys)
     {
         vec.Set(v);
     }
     return new IntersectOp(vec, leftMap, rightMap);
 }
 public ChainedMap(VarMap <K, V> next)
 {
     _next = next;
     _map  = new HashMap <K, V>();
 }
        private VarMap FlattenVarMap(VarMap varMap, out List<ComputedVar> newComputedVars)
        {
            newComputedVars = null;

            var newVarMap = new VarMap();
            foreach (var kv in varMap)
            {
                VarInfo innerVarInfo;
                VarInfo outerVarInfo;
                // Does the inner var have a Varinfo - if not, simply add it 
                // to the VarMap, and continue.
                // Otherwise, the Outer var must have a VarInfo too
                if (!m_varInfoMap.TryGetVarInfo(kv.Value, out innerVarInfo))
                {
                    newVarMap.Add(kv.Key, kv.Value);
                }
                else
                {
                    // get my own var info
                    if (!m_varInfoMap.TryGetVarInfo(kv.Key, out outerVarInfo))
                    {
                        outerVarInfo = FlattenSetOpVar((SetOpVar)kv.Key);
                    }

                    // If this Var represents a collection type, then simply 
                    // replace the singleton Var
                    if (outerVarInfo.Kind
                        == VarInfoKind.CollectionVarInfo)
                    {
                        newVarMap.Add(((CollectionVarInfo)outerVarInfo).NewVar, ((CollectionVarInfo)innerVarInfo).NewVar);
                    }
                    else if (outerVarInfo.Kind
                             == VarInfoKind.PrimitiveTypeVarInfo)
                    {
                        newVarMap.Add(((PrimitiveTypeVarInfo)outerVarInfo).NewVar, ((PrimitiveTypeVarInfo)innerVarInfo).NewVar);
                    }
                    else
                    {
                        // structured type 
                        Debug.Assert(outerVarInfo.Kind == VarInfoKind.StructuredTypeVarInfo, "StructuredVarInfo expected");

                        var outerSvarInfo = (StructuredVarInfo)outerVarInfo;
                        var innerSvarInfo = (StructuredVarInfo)innerVarInfo;

                        // walk through each property, and find the innerVar corresponding
                        // to that property
                        foreach (var prop in outerSvarInfo.Fields)
                        {
                            Var outerVar;
                            Var innerVar;
                            var ret = outerSvarInfo.TryGetVar(prop, out outerVar);
                            PlanCompiler.Assert(ret, "Could not find VarInfo for prop " + prop.Name);

                            if (!innerSvarInfo.TryGetVar(prop, out innerVar))
                            {
                                // we didn't find a corresponding innerVar. 
                                innerVar = m_command.CreateComputedVar(outerVar.Type);
                                if (newComputedVars == null)
                                {
                                    newComputedVars = new List<ComputedVar>();
                                }
                                newComputedVars.Add((ComputedVar)innerVar);
                            }
                            newVarMap.Add(outerVar, innerVar);
                        }
                    }
                }
            }
            return newVarMap;
        }
示例#16
0
        // <summary>
        // Common copy path for all SetOps
        // </summary>
        // <param name="op"> The SetOp to Copy (must be one of ExceptOp, IntersectOp, UnionAllOp) </param>
        // <param name="n"> The Node that references the Op </param>
        // <returns> A copy of the original Node that references a copy of the original Op </returns>
        private Node CopySetOp(SetOp op, Node n)
        {
            // Visit the Node's children and map their Vars
            var children = ProcessChildren(n);

            var leftMap = new VarMap();
            var rightMap = new VarMap();

            foreach (var kv in op.VarMap[0])
            {
                // Create a new output Var that is a copy of the original output Var
                Var outputVar = m_destCmd.CreateSetOpVar(kv.Key.Type);

                // Add a mapping for the new output var we've just created
                SetMappedVar(kv.Key, outputVar);

                // Add this output var's entries to the new VarMaps
                leftMap.Add(outputVar, GetMappedVar(kv.Value));
                rightMap.Add(outputVar, GetMappedVar((op.VarMap[1])[kv.Key]));
            }

            SetOp newSetOp = null;
            switch (op.OpType)
            {
                case OpType.UnionAll:
                    {
                        var branchDiscriminator = ((UnionAllOp)op).BranchDiscriminator;
                        if (null != branchDiscriminator)
                        {
                            branchDiscriminator = GetMappedVar(branchDiscriminator);
                        }
                        newSetOp = m_destCmd.CreateUnionAllOp(leftMap, rightMap, branchDiscriminator);
                    }
                    break;

                case OpType.Intersect:
                    {
                        newSetOp = m_destCmd.CreateIntersectOp(leftMap, rightMap);
                    }
                    break;

                case OpType.Except:
                    {
                        newSetOp = m_destCmd.CreateExceptOp(leftMap, rightMap);
                    }
                    break;

                default:
                    {
                        Debug.Assert(false, "Unexpected SetOpType");
                    }
                    break;
            }

            return m_destCmd.CreateNode(newSetOp, children);
        }
示例#17
0
        // <summary>
        // Convert a SingleStreamNestOp into a massive UnionAllOp
        // </summary>
        private Node BuildUnionAllSubqueryForNestOp(
            NestBaseOp nestOp, Node nestNode, VarList drivingNodeVars, VarList discriminatorVarList, out Var discriminatorVar,
            out List<Dictionary<Var, Var>> varMapList)
        {
            var drivingNode = nestNode.Child0;

            // For each of the NESTED collections...
            Node unionAllNode = null;
            VarList unionAllOutputs = null;
            for (var i = 1; i < nestNode.Children.Count; i++)
            {
                // Ensure we only use the driving collection tree once, so other
                // transformations do not unintentionally change more than one path.
                // To prevent nodes in the tree from being used in multiple paths,
                // we copy the driving input on successive nodes.
                VarList newDrivingNodeVars;
                Node newDrivingNode;
                VarList newFlattenedElementVars;
                Op op;

                if (i > 1)
                {
                    newDrivingNode = OpCopier.Copy(Command, drivingNode, drivingNodeVars, out newDrivingNodeVars);
                    // 
                    // Bug 450245: If we copied the driver node, then references to driver node vars
                    // from the collection subquery must be patched up
                    //
                    var varRemapper = new VarRemapper(Command);
                    for (var j = 0; j < drivingNodeVars.Count; j++)
                    {
                        varRemapper.AddMapping(drivingNodeVars[j], newDrivingNodeVars[j]);
                    }
                    // Remap all references in the current subquery
                    varRemapper.RemapSubtree(nestNode.Children[i]);

                    // Bug 479183: Remap the flattened element vars
                    newFlattenedElementVars = varRemapper.RemapVarList(nestOp.CollectionInfo[i - 1].FlattenedElementVars);

                    // Create a cross apply for all but the first collection
                    op = Command.CreateCrossApplyOp();
                }
                else
                {
                    newDrivingNode = drivingNode;
                    newDrivingNodeVars = drivingNodeVars;
                    newFlattenedElementVars = nestOp.CollectionInfo[i - 1].FlattenedElementVars;

                    // Create an outer apply for the first collection, 
                    // that way we ensure at least one row for each row in the driver node.
                    op = Command.CreateOuterApplyOp();
                }

                // Create an outer apply with the driver node and the nested collection.
                var applyNode = Command.CreateNode(op, newDrivingNode, nestNode.Children[i]);

                // Now create a ProjectOp that augments the output from the OuterApplyOp
                // with nulls for each column from other collections

                // Build the VarDefList (the list of vars) for the Project, starting
                // with the collection discriminator var
                var varDefListChildren = new List<Node>();
                var projectOutputs = Command.CreateVarList();

                // Add the collection discriminator var to the output.
                projectOutputs.Add(discriminatorVarList[i]);

                // Add all columns from the driving node
                projectOutputs.AddRange(newDrivingNodeVars);

                // Add all the vars from all the nested collections;
                for (var j = 1; j < nestNode.Children.Count; j++)
                {
                    var otherCollectionInfo = nestOp.CollectionInfo[j - 1];
                    // For the current nested collection, we just pick the var that's
                    // coming from there and don't need have a new var defined, but for
                    // the rest we construct null values.
                    if (i == j)
                    {
                        projectOutputs.AddRange(newFlattenedElementVars);
                    }
                    else
                    {
                        foreach (var v in otherCollectionInfo.FlattenedElementVars)
                        {
                            var nullOp = Command.CreateNullOp(v.Type);
                            var nullOpNode = Command.CreateNode(nullOp);
                            Var nullOpVar;
                            var nullOpVarDefNode = Command.CreateVarDefNode(nullOpNode, out nullOpVar);
                            varDefListChildren.Add(nullOpVarDefNode);
                            projectOutputs.Add(nullOpVar);
                        }
                    }
                }

                var varDefListNode = Command.CreateNode(Command.CreateVarDefListOp(), varDefListChildren);

                // Now, build up the projectOp
                var projectOutputsVarSet = Command.CreateVarVec(projectOutputs);
                var projectOp = Command.CreateProjectOp(projectOutputsVarSet);
                var projectNode = Command.CreateNode(projectOp, applyNode, varDefListNode);

                // finally, build the union all
                if (unionAllNode == null)
                {
                    unionAllNode = projectNode;
                    unionAllOutputs = projectOutputs;
                }
                else
                {
                    var unionAllMap = new VarMap();
                    var projectMap = new VarMap();
                    for (var idx = 0; idx < unionAllOutputs.Count; idx++)
                    {
                        Var outputVar = Command.CreateSetOpVar(unionAllOutputs[idx].Type);
                        unionAllMap.Add(outputVar, unionAllOutputs[idx]);
                        projectMap.Add(outputVar, projectOutputs[idx]);
                    }
                    var unionAllOp = Command.CreateUnionAllOp(unionAllMap, projectMap);
                    unionAllNode = Command.CreateNode(unionAllOp, unionAllNode, projectNode);

                    // Get the output vars from the union-op. This must be in the same order
                    // as the original list of Vars
                    unionAllOutputs = GetUnionOutputs(unionAllOp, unionAllOutputs);
                }
            }

            // We're done building the node, but now we have to build a mapping from
            // the before-Vars to the after-Vars
            varMapList = new List<Dictionary<Var, Var>>();
            IEnumerator<Var> outputVarsEnumerator = unionAllOutputs.GetEnumerator();
            if (!outputVarsEnumerator.MoveNext())
            {
                throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.ColumnCountMismatch, 4, null);
                // more columns from children than are on the unionAll?
            }
            // The discriminator var is always first
            discriminatorVar = outputVarsEnumerator.Current;

            // Build a map for each input
            for (var i = 0; i < nestNode.Children.Count; i++)
            {
                var varMap = new Dictionary<Var, Var>();
                var varList = (i == 0) ? drivingNodeVars : nestOp.CollectionInfo[i - 1].FlattenedElementVars;
                foreach (var v in varList)
                {
                    if (!outputVarsEnumerator.MoveNext())
                    {
                        throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.ColumnCountMismatch, 5, null);
                        // more columns from children than are on the unionAll?
                    }
                    varMap[v] = outputVarsEnumerator.Current;
                }
                varMapList.Add(varMap);
            }
            if (outputVarsEnumerator.MoveNext())
            {
                throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.ColumnCountMismatch, 6, null);
                // at this point, we better be done with both lists...
            }

            return unionAllNode;
        }
示例#18
0
 public void SetVarMap(VarMap varMap)
 {
     m_varMap = varMap;
 }