//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Collections.Generic;
using System.Globalization;
namespace Microsoft.SqlTools.ServiceLayer.ShowPlan.ShowPlanGraph
{
///
/// Parses stytement type ShowPlan XML nodes
///
internal class StatementParser : XmlPlanParser
{
///
/// Creates new node and adds it to the graph.
///
/// Item being parsed.
/// Parent item.
/// Parent node.
/// Node builder context.
/// The node that corresponds to the item being parsed.
public override Node GetCurrentNode(object item, object parentItem, Node parentNode, NodeBuilderContext context)
{
return NewNode(context);
}
///
/// Determines Operation that corresponds to the object being parsed.
///
/// Node being parsed.
/// Operation that corresponds to the node.
protected override Operation GetNodeOperation(Node node)
{
object statementType = node["StatementType"];
Operation statement = statementType != null
? OperationTable.GetStatement(statementType.ToString())
: Operation.Unknown;
return statement;
}
///
/// Determines node subtree cost from existing node properties.
///
/// Node being parsed.
/// Node subtree cost.
protected override double GetNodeSubtreeCost(Node node)
{
object value = node["StatementSubTreeCost"];
return value != null ? Convert.ToDouble(value, CultureInfo.CurrentCulture) : 0;
}
protected override bool ShouldParseItem(object parsedItem)
{
// Special case. An empty statement without QueryPlan but with
// a UDF or StoreProc should be skipped
StmtSimpleType statement = parsedItem as StmtSimpleType;
if (statement != null)
{
// We use hidden wrapper statements for UDFs and StoredProcs
// Hidden statements don't have any of their properties defined
// We can use one of properties which is always set by server
// such as StatementIdSpecified to distinguish between a real
// statement and a hidden wrapper statement
if (!statement.StatementIdSpecified)
{
return false;
}
}
// By default, the statement is parsed
return true;
}
///
/// Enumerates FunctionType blocks and removes all items from UDF and StoredProc properties.
///
/// The item being parsed.
/// Enumeration.
public override IEnumerable ExtractFunctions(object parsedItem)
{
StmtSimpleType statement = parsedItem as StmtSimpleType;
if (statement != null)
{
// If this is a simple statement it may have UDF and StoredProc fields
if (statement.UDF != null)
{
foreach (FunctionType function in statement.UDF)
{
yield return new FunctionTypeItem(function, FunctionTypeItem.ItemType.Udf);
}
statement.UDF = null;
}
if (statement.StoredProc != null)
{
yield return new FunctionTypeItem(statement.StoredProc, FunctionTypeItem.ItemType.StoredProcedure);
statement.StoredProc = null;
}
}
else
{
// This is some other type of Statement. Call ExtractFunctions for all its children
foreach (object item in GetChildren(parsedItem))
{
XmlPlanParser parser = XmlPlanParserFactory.GetParser(item.GetType());
foreach (FunctionTypeItem functionItem in parser.ExtractFunctions(item))
{
yield return functionItem;
}
}
}
yield break;
}
///
/// protected constructor prevents this object from being externally instantiated
///
protected StatementParser()
{
}
///
/// Singelton instance
///
private static StatementParser statementParser = null;
public static StatementParser Instance
{
get
{
if (statementParser == null)
{
statementParser = new StatementParser();
}
return statementParser;
}
}
}
}