protected override Operation GetNodeOperation()

in src/Microsoft.SqlTools.ServiceLayer/ShowPlan/ShowPlanGraph/RelOpTypeParser.cs [76:190]


        protected override Operation GetNodeOperation(Node node)
        {
            object physicalOpType = node["PhysicalOp"];
            object logicalOpType = node["LogicalOp"];

            if (physicalOpType == null || logicalOpType == null)
            {
                throw new FormatException(SR.Keys.UnknownShowPlanSource);
            }

            string physicalOpTypeName = physicalOpType.ToString();
            string logicalOpTypeName = logicalOpType.ToString();

            // SQLBU# 434739: Custom description and icons for KeyLookup operation:
            //
            // SQL Server 2005 doesnt expose 'KeyLookup' operations as thier own type,
            // instead they indicate Bookmark operations as a 'ClusteredIndexSeek' op
            // that is having Lookup=true. Users have to select the actual node to tell
            // if a ClusteredIndexSeek is an actual bookmark operation or not.
            //
            // Our request for having engine expose the Bookmark operation as its own type,
            // instead of exposing it as a 'ClusteredIndexSeek' cannot be addressed by
            // engine in SP2 timeframe (reasons include compatibility on published showplanxml.xsd
            // schema as well as amount of changes in components that consume the xml showplan)
            //
            // For SP2 timeframe the solution is to do an aesthetic only change:
            // SSMS interprets the xml showplan and provides custom icons and descriptions
            // for a new operation: 'KeyLookup', that is getting documented in BOL.
            const string operationClusteredIndexSeek = "ClusteredIndexSeek";
            const string operationKeyLookup = "KeyLookup";

            object lookup = node["Lookup"];
            if ((lookup != null) && (lookup is System.Boolean))
            {
                if (Convert.ToBoolean(lookup) == true)
                {
                    if (0 == string.Compare(physicalOpTypeName, operationClusteredIndexSeek, StringComparison.OrdinalIgnoreCase))
                    {
                        physicalOpTypeName = operationKeyLookup;
                    }
                    if (0 == string.Compare(logicalOpTypeName, operationClusteredIndexSeek, StringComparison.OrdinalIgnoreCase))
                    {
                        logicalOpTypeName = operationKeyLookup;
                    }
                }
            }

            /*
             * For index scans, Storage property should be read from this node.
             * Otherwise, for DML operations, Storage property should be read from this node's child "Object" element.
             */
            if (0 == string.Compare(physicalOpTypeName, OPERATION_INDEX_SCAN, StringComparison.OrdinalIgnoreCase) ||
                0 == string.Compare(physicalOpTypeName, OPERATION_CLUSTERED_INDEX_SCAN, StringComparison.OrdinalIgnoreCase))
            {
                object storage = node[STORAGE_PROPERTY];
                if ((storage != null) && (storage.Equals(StorageType.ColumnStore)))
                {
                    physicalOpTypeName = OPERATION_COLUMNSTORE_INDEX_SCAN;
                }
            }
            else
            {
                ExpandableObjectWrapper objectWrapper = (ExpandableObjectWrapper)node[OBJECT_NODE];
                if (objectWrapper != null)
                {
                    PropertyValue storagePropertyValue = (PropertyValue)objectWrapper.Properties[STORAGE_PROPERTY];

                    /*
                     * If object's storage is of type Storage.Columnstore,
                     * PhysicalOperations should be updated to their columnstore counterparts.
                     */
                    if (storagePropertyValue != null && ((storagePropertyValue).Value.Equals(StorageType.ColumnStore)))
                    {
                        if (0 == string.Compare(physicalOpTypeName, OPERATION_INDEX_DELETE, StringComparison.OrdinalIgnoreCase) ||
                            0 == string.Compare(physicalOpTypeName, OPERATION_CLUSTERED_INDEX_DELETE, StringComparison.OrdinalIgnoreCase))
                        {
                            physicalOpTypeName = OPERATION_COLUMNSTORE_INDEX_DELETE;
                        }
                        else if (0 == string.Compare(physicalOpTypeName, OPERATION_INDEX_INSERT, StringComparison.OrdinalIgnoreCase) ||
                                 0 == string.Compare(physicalOpTypeName, OPERATION_CLUSTERED_INDEX_INSERT, StringComparison.OrdinalIgnoreCase))
                        {
                            physicalOpTypeName = OPERATION_COLUMNSTORE_INDEX_INSERT;
                        }
                        else if (0 == string.Compare(physicalOpTypeName, OPERATION_INDEX_MERGE, StringComparison.OrdinalIgnoreCase) ||
                                 0 == string.Compare(physicalOpTypeName, OPERATION_CLUSTERED_INDEX_MERGE, StringComparison.OrdinalIgnoreCase))
                        {
                            physicalOpTypeName = OPERATION_COLUMNSTORE_INDEX_MERGE;
                        }
                        else if (0 == string.Compare(physicalOpTypeName, OPERATION_INDEX_UPDATE, StringComparison.OrdinalIgnoreCase) ||
                                 0 == string.Compare(physicalOpTypeName, OPERATION_CLUSTERED_INDEX_UPDATE, StringComparison.OrdinalIgnoreCase))
                        {
                            physicalOpTypeName = OPERATION_COLUMNSTORE_INDEX_UPDATE;
                        }
                    }
                }
            }

            Operation physicalOp = OperationTable.GetPhysicalOperation(physicalOpTypeName);
            Operation logicalOp = OperationTable.GetLogicalOperation(logicalOpTypeName);

            Operation resultOp = logicalOp != null && logicalOp.Image != null && logicalOp.Description != null
                ? logicalOp : physicalOp;

            node.LogicalOpUnlocName = logicalOpTypeName;
            node.PhysicalOpUnlocName = physicalOpTypeName;
            node["PhysicalOp"] = physicalOp.DisplayName;
            node["LogicalOp"] = logicalOp.DisplayName;

            Debug.Assert(logicalOp.DisplayName != null);
            Debug.Assert(physicalOp.DisplayName != null);
            Debug.Assert(resultOp.Description != null);
            Debug.Assert(resultOp.Image != null);

            return resultOp;
        }