Example #1
0
        /// <summary>
        ///     Computes a NodeInfo for a NestOp (SingleStream/MultiStream).
        ///     Definitions = OutputVars
        ///     LocalDefinitions = Collection Vars
        ///     Keys = Keys of my child
        ///     External References = any external references from the inputs
        ///     RowCount=default
        /// </summary>
        /// <param name="op"> The NestOp </param>
        /// <param name="n"> corresponding Node </param>
        protected override NodeInfo VisitNestOp(NestBaseOp op, Node n)
        {
            var ssnOp    = op as SingleStreamNestOp;
            var nodeInfo = InitExtendedNodeInfo(n);

            foreach (var ci in op.CollectionInfo)
            {
                nodeInfo.LocalDefinitions.Set(ci.CollectionVar);
            }
            nodeInfo.Definitions.InitFrom(op.Outputs);

            // get external references from each child
            foreach (var chi in n.Children)
            {
                nodeInfo.ExternalReferences.Or(GetExtendedNodeInfo(chi).ExternalReferences);
            }

            // eliminate things I may have defined already (left correlation)
            nodeInfo.ExternalReferences.Minus(nodeInfo.Definitions);

            // Keys are from the driving node only.
            if (ssnOp == null)
            {
                nodeInfo.Keys.InitFrom(GetExtendedNodeInfo(n.Child0).Keys);
            }
            else
            {
                nodeInfo.Keys.InitFrom(ssnOp.Keys);
            }
            return(nodeInfo);
        }
        protected override NodeInfo VisitNestOp(NestBaseOp op, Node n)
        {
            SingleStreamNestOp singleStreamNestOp = op as SingleStreamNestOp;
            ExtendedNodeInfo   extendedNodeInfo   = this.InitExtendedNodeInfo(n);

            foreach (CollectionInfo collectionInfo in op.CollectionInfo)
            {
                extendedNodeInfo.LocalDefinitions.Set(collectionInfo.CollectionVar);
            }
            extendedNodeInfo.Definitions.InitFrom(op.Outputs);
            foreach (Node child in n.Children)
            {
                extendedNodeInfo.ExternalReferences.Or(this.GetExtendedNodeInfo(child).ExternalReferences);
            }
            extendedNodeInfo.ExternalReferences.Minus(extendedNodeInfo.Definitions);
            if (singleStreamNestOp == null)
            {
                extendedNodeInfo.Keys.InitFrom(this.GetExtendedNodeInfo(n.Child0).Keys);
            }
            else
            {
                extendedNodeInfo.Keys.InitFrom((IEnumerable <Var>)singleStreamNestOp.Keys);
            }
            return((NodeInfo)extendedNodeInfo);
        }
Example #3
0
        private Node VisitNestOp(Node n)
        {
            var op    = n.Op as NestBaseOp;
            var ssnOp = op as SingleStreamNestOp;

            Debug.Assert(op != null);

            // Visit the Node's children and map their Vars
            var newChildren = ProcessChildren(n);

            Var newDiscriminator = null;

            if (ssnOp != null)
            {
                newDiscriminator = GetMappedVar(ssnOp.Discriminator);
            }
            var newCollectionInfoList = new List <CollectionInfo>();

            foreach (var ci in op.CollectionInfo)
            {
                var newColumnMap = Copy(ci.ColumnMap);

                Var newCollectionVar = m_destCmd.CreateComputedVar(ci.CollectionVar.Type);
                SetMappedVar(ci.CollectionVar, newCollectionVar);

                var newFlattendElementVars = Copy(ci.FlattenedElementVars);
                var newKeys           = Copy(ci.Keys);
                var newSortKeys       = Copy(ci.SortKeys);
                var newCollectionInfo = Command.CreateCollectionInfo(
                    newCollectionVar, newColumnMap, newFlattendElementVars, newKeys, newSortKeys, ci.DiscriminatorValue);
                newCollectionInfoList.Add(newCollectionInfo);
            }

            var newOutputs = Copy(op.Outputs);

            NestBaseOp newOp             = null;
            var        newPrefixSortKeys = Copy(op.PrefixSortKeys);

            if (ssnOp != null)
            {
                var newKeys = Copy(ssnOp.Keys);
                // Copy the SortOp's SortKeys
                var newPostfixSortKeys = Copy(ssnOp.PostfixSortKeys);
                newOp = m_destCmd.CreateSingleStreamNestOp(
                    newKeys, newPrefixSortKeys, newPostfixSortKeys, newOutputs, newCollectionInfoList, newDiscriminator);
            }
            else
            {
                newOp = m_destCmd.CreateMultiStreamNestOp(newPrefixSortKeys, newOutputs, newCollectionInfoList);
            }

            return(m_destCmd.CreateNode(newOp, newChildren));
        }
        private Node VisitNestOp(Node n)
        {
            NestBaseOp         op = n.Op as NestBaseOp;
            SingleStreamNestOp singleStreamNestOp = op as SingleStreamNestOp;
            List <Node>        args = this.ProcessChildren(n);
            Var discriminatorVar    = (Var)null;

            if (singleStreamNestOp != null)
            {
                discriminatorVar = this.GetMappedVar(singleStreamNestOp.Discriminator);
            }
            List <CollectionInfo> collectionInfoList = new List <CollectionInfo>();

            foreach (CollectionInfo collectionInfo1 in op.CollectionInfo)
            {
                ColumnMap columnMap   = this.Copy(collectionInfo1.ColumnMap);
                Var       computedVar = (Var)this.m_destCmd.CreateComputedVar(collectionInfo1.CollectionVar.Type);
                this.SetMappedVar(collectionInfo1.CollectionVar, computedVar);
                VarList        flattenedElementVars = this.Copy(collectionInfo1.FlattenedElementVars);
                VarVec         keys            = this.Copy(collectionInfo1.Keys);
                List <SortKey> sortKeys        = this.Copy(collectionInfo1.SortKeys);
                CollectionInfo collectionInfo2 = Command.CreateCollectionInfo(computedVar, columnMap, flattenedElementVars, keys, sortKeys, collectionInfo1.DiscriminatorValue);
                collectionInfoList.Add(collectionInfo2);
            }
            VarVec         outputVars     = this.Copy(op.Outputs);
            List <SortKey> prefixSortKeys = this.Copy(op.PrefixSortKeys);
            NestBaseOp     nestBaseOp;

            if (singleStreamNestOp != null)
            {
                VarVec         keys            = this.Copy(singleStreamNestOp.Keys);
                List <SortKey> postfixSortKeys = this.Copy(singleStreamNestOp.PostfixSortKeys);
                nestBaseOp = (NestBaseOp)this.m_destCmd.CreateSingleStreamNestOp(keys, prefixSortKeys, postfixSortKeys, outputVars, collectionInfoList, discriminatorVar);
            }
            else
            {
                nestBaseOp = (NestBaseOp)this.m_destCmd.CreateMultiStreamNestOp(prefixSortKeys, outputVars, collectionInfoList);
            }
            return(this.m_destCmd.CreateNode((Op)nestBaseOp, args));
        }
Example #5
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;
        }
Example #6
0
        // <summary>
        // "Normalize" each input to the NestOp.
        // We're now in the context of a MultiStreamNestOp, and we're trying to convert this
        // into a SingleStreamNestOp.
        // Normalization specifically refers to
        // - augmenting each input with a discriminator value (that describes the collection)
        // - removing the sort node at the root (and capturing this information as part of the sortkeys)
        // </summary>
        // <param name="nestOp"> the nestOp </param>
        // <param name="nestNode"> the nestOp subtree </param>
        // <param name="discriminatorVarList"> Discriminator Vars for each Collection input </param>
        // <param name="sortKeys"> SortKeys (postfix) for each Collection input </param>
        private void NormalizeNestOpInputs(
            NestBaseOp nestOp, Node nestNode, out VarList discriminatorVarList, out List<List<SortKey>> sortKeys)
        {
            discriminatorVarList = Command.CreateVarList();

            // We insert a dummy var and value at poistion 0 for the deriving node, which
            // we should never reference;
            discriminatorVarList.Add(null);

            sortKeys = new List<List<SortKey>>();
            sortKeys.Add(nestOp.PrefixSortKeys);

            for (var i = 1; i < nestNode.Children.Count; i++)
            {
                var inputNode = nestNode.Children[i];
                // Since we're called from ConvertToSingleStreamNest, it is possible that we have a 
                // SingleStreamNest here, because the input to the MultiStreamNest we're converting 
                // may have been a MultiStreamNest that was converted to a SingleStreamNest.
                var ssnOp = inputNode.Op as SingleStreamNestOp;

                // If this collection is a SingleStreamNest, we pull up the key information
                // in it, and pullup the input;
                if (null != ssnOp)
                {
                    // Note that the sortKeys argument is 1:1 with the nestOp inputs, that is
                    // each input may have exactly one entry in the list, so we have to combine
                    // all of the sort key components (Prefix+Keys+Discriminator+PostFix) into
                    // one list.
                    var mySortKeys = BuildSortKeyList(ssnOp);
                    sortKeys.Add(mySortKeys);

                    inputNode = inputNode.Child0;
                }
                else
                {
                    // If the current collection has a SortNode specified, then pull that
                    // out, and add the information to the list of postfix SortColumns
                    var sortOp = inputNode.Op as SortOp;
                    if (null != sortOp)
                    {
                        inputNode = inputNode.Child0; // bypass the sort node
                        // Add the sort keys to the list of postfix sort keys
                        sortKeys.Add(sortOp.Keys);
                    }
                    else
                    {
                        // No postfix sort keys for this case
                        sortKeys.Add(new List<SortKey>());
                    }
                }

                // #447304: Ensure that any SortKey Vars will be projected from the input in addition to showing up in the postfix sort keys
                // by adding them to the FlattenedElementVars for this NestOp input's CollectionInfo.
                var flattenedElementVars = nestOp.CollectionInfo[i - 1].FlattenedElementVars;
                foreach (var sortKey in sortKeys[i])
                {
                    if (!flattenedElementVars.Contains(sortKey.Var))
                    {
                        flattenedElementVars.Add(sortKey.Var);
                    }
                }

                // Add a discriminator column to the collection-side - this must
                // happen before the outer-apply is added on; we need to use the value of
                // the discriminator to distinguish between null and empty collections
                Var discriminatorVar;
                var augmentedInput = AugmentNodeWithInternalIntegerConstant(inputNode, i, out discriminatorVar);
                nestNode.Children[i] = augmentedInput;
                discriminatorVarList.Add(discriminatorVar);
            }
        }
Example #7
0
        // <summary>
        // MultiStreamNestOp/SingleStreamNestOp common processing.
        // Pretty much just verifies that we didn't leave a NestOp behind.
        // </summary>
        protected override Node VisitNestOp(NestBaseOp op, Node n)
        {
            // First, visit my children
            VisitChildren(n);

            // If any of the children are a nestOp, then we have a
            // problem; it shouldn't have happened.
            foreach (var chi in n.Children)
            {
                if (IsNestOpNode(chi))
                {
                    throw new InvalidOperationException(Strings.ADP_InternalProviderError((int)EntityUtil.InternalErrorCode.NestOverNest));
                }
            }
            return n;
        }
Example #8
0
        private NestBaseOp GetNestOpWithConsolidatedSortKeys(NestBaseOp inputNestOp, List<SortKey> sortKeys)
        {
            NestBaseOp result;

            // Include the  sort keys as the prefix sort keys;
            // Note that we can't actually have a SSNest at this point in
            // the tree; they're only introduced once we've processed the
            // entire tree.

            if (inputNestOp.PrefixSortKeys.Count == 0)
            {
                foreach (var sk in sortKeys)
                {
                    //SQLBUDT #507170 - We can't just add the sort keys, we need to copy them, 
                    // to avoid changes to one to affect the other
                    inputNestOp.PrefixSortKeys.Add(Command.CreateSortKey(sk.Var, sk.AscendingSort, sk.Collation));
                }
                result = inputNestOp;
            }
            else
            {
                var sortVars = Command.CreateVarVec();

                // First add the sort keys from the SortBaseOp, then the NestOp keys
                var sortKeyList = ConsolidateSortKeys(sortKeys, inputNestOp.PrefixSortKeys);

                PlanCompiler.Assert(inputNestOp is MultiStreamNestOp, "Unexpected SingleStreamNestOp?");

                // Finally, build a new NestOp with the keys...
                result = Command.CreateMultiStreamNestOp(sortKeyList, inputNestOp.Outputs, inputNestOp.CollectionInfo);
            }
            return result;
        }
Example #9
0
        protected override void VisitNestOp(NestBaseOp op, Node n)
        {
            var attrs = new Dictionary <string, object>();

            var ssnOp = op as SingleStreamNestOp;

            if (null != ssnOp)
            {
                attrs.Add("Discriminator", (ssnOp.Discriminator == null) ? "<null>" : ssnOp.Discriminator.ToString());
            }

            var    sb = new StringBuilder();
            string separator;

            if (null != ssnOp)
            {
                sb.Length = 0;
                separator = string.Empty;
                foreach (var v in ssnOp.Keys)
                {
                    sb.Append(separator);
                    sb.Append(v.Id);
                    separator = ",";
                }
                if (0 != sb.Length)
                {
                    attrs.Add("Keys", sb.ToString());
                }
            }

            using (new AutoXml(this, op, attrs))
            {
                using (new AutoXml(this, "outputs"))
                {
                    foreach (var v in op.Outputs)
                    {
                        DumpVar(v);
                    }
                }
                foreach (var ci in op.CollectionInfo)
                {
                    var attrs2 = new Dictionary <string, object>();
                    attrs2.Add("CollectionVar", ci.CollectionVar);

                    if (null != ci.DiscriminatorValue)
                    {
                        attrs2.Add("DiscriminatorValue", ci.DiscriminatorValue);
                    }
                    if (0 != ci.FlattenedElementVars.Count)
                    {
                        attrs2.Add("FlattenedElementVars", FormatVarList(sb, ci.FlattenedElementVars));
                    }
                    if (0 != ci.Keys.Count)
                    {
                        attrs2.Add("Keys", ci.Keys);
                    }
                    if (0 != ci.SortKeys.Count)
                    {
                        attrs2.Add("SortKeys", FormatVarList(sb, ci.SortKeys));
                    }
                    using (new AutoXml(this, "collection", attrs2))
                    {
                        ci.ColumnMap.Accept(ColumnMapDumper.Instance, this);
                    }
                }
                VisitChildren(n);
            }
        }
 /// <summary>
 ///     Common handling for all nestOps
 /// </summary>
 /// <param name="op"> nest op </param>
 /// <param name="n"> </param>
 protected virtual void VisitNestOp(NestBaseOp op, Node n)
 {
     VisitPhysicalOpDefault(op, n);
 }
        protected override void VisitNestOp(NestBaseOp op, Node n)
        {
            Dictionary <string, object> attrs1             = new Dictionary <string, object>();
            SingleStreamNestOp          singleStreamNestOp = op as SingleStreamNestOp;

            if (singleStreamNestOp != null)
            {
                attrs1.Add("Discriminator", singleStreamNestOp.Discriminator == null ? (object)"<null>" : (object)singleStreamNestOp.Discriminator.ToString());
            }
            StringBuilder sb = new StringBuilder();

            if (singleStreamNestOp != null)
            {
                sb.Length = 0;
                string str = string.Empty;
                foreach (Var key in singleStreamNestOp.Keys)
                {
                    sb.Append(str);
                    sb.Append(key.Id);
                    str = ",";
                }
                if (sb.Length != 0)
                {
                    attrs1.Add("Keys", (object)sb.ToString());
                }
            }
            using (new Dump.AutoXml(this, (Op)op, attrs1))
            {
                using (new Dump.AutoXml(this, "outputs"))
                {
                    foreach (Var output in op.Outputs)
                    {
                        this.DumpVar(output);
                    }
                }
                foreach (CollectionInfo collectionInfo in op.CollectionInfo)
                {
                    Dictionary <string, object> attrs2 = new Dictionary <string, object>();
                    attrs2.Add("CollectionVar", (object)collectionInfo.CollectionVar);
                    if (collectionInfo.DiscriminatorValue != null)
                    {
                        attrs2.Add("DiscriminatorValue", collectionInfo.DiscriminatorValue);
                    }
                    if (collectionInfo.FlattenedElementVars.Count != 0)
                    {
                        attrs2.Add("FlattenedElementVars", (object)Dump.FormatVarList(sb, collectionInfo.FlattenedElementVars));
                    }
                    if (collectionInfo.Keys.Count != 0)
                    {
                        attrs2.Add("Keys", (object)collectionInfo.Keys);
                    }
                    if (collectionInfo.SortKeys.Count != 0)
                    {
                        attrs2.Add("SortKeys", (object)Dump.FormatVarList(sb, collectionInfo.SortKeys));
                    }
                    using (new Dump.AutoXml(this, "collection", attrs2))
                        collectionInfo.ColumnMap.Accept <Dump>((ColumnMapVisitor <Dump>)Dump.ColumnMapDumper.Instance, this);
                }
                this.VisitChildren(n);
            }
        }
Example #12
0
 protected override void VisitNestOp(NestBaseOp op, Node n)
 {
     throw new NotSupportedException();
 }
 protected virtual void VisitNestOp(NestBaseOp op, Node n)
 {
     this.VisitPhysicalOpDefault((PhysicalOp)op, n);
 }
Example #14
0
 // <summary>
 // A default processor for all NestOps.
 // Allows new visitors to just override this to handle all NestOps
 // </summary>
 // <param name="op"> the NestOp </param>
 // <param name="n"> the node to process </param>
 // <returns> a potentially modified subtree </returns>
 protected virtual TResultType VisitNestOp(NestBaseOp op, Node n)
 {
     return(VisitPhysicalOpDefault(op, n));
 }