private static string ExtractConstant(SqlParseTreeNode node)
        {
            string pattern = @"XVAR\((?<dataType>.+?),(?<ownership>.+?),\s*Value=(?<value>.+?)\)";
            Match  match   = Regex.Match(node.Arguments, pattern);

            if (match.Success)
            {
                string dataType  = match.Groups["dataType"].Value;
                string ownership = match.Groups["ownership"].Value;
                string value     = match.Groups["value"].Value;

                if (value.StartsWith("Len,Data = "))
                {
                    value  += ")";
                    pattern = @"\((?<length>.+?),(?<value>.+?)\)";
                    match   = Regex.Match(value, pattern);
                    if (match.Success)
                    {
                        string length = match.Groups["length"].Value;
                        value = match.Groups["value"].Value;
                    }
                }

                return($"({dataType}) {value.Trim()}");
            }

            return("<unknown>");
        }
        private static string ExtractTableNameAndAlias(SqlParseTreeNode node)
        {
            // Quick and dirty; probably has some cases where this isn't going to work
            if (string.IsNullOrEmpty(node.Arguments))
            {
                return(string.Empty);
            }

            string tableLabel = "TBL: ";
            string aliasLabel = "alias TBL: ";

            int tableLabelIndex = node.Arguments.IndexOf(tableLabel, StringComparison.InvariantCultureIgnoreCase);

            if (tableLabelIndex < 0)
            {
                return(string.Empty);
            }

            bool          inEscape        = false;
            bool          hasAlias        = false;
            int           aliasStartIndex = 0;
            StringBuilder sb = new StringBuilder();

            for (int index = tableLabelIndex + tableLabel.Length; index < node.Arguments.Length; index++)
            {
                char c = node.Arguments[index];
                if (c == '[')
                {
                    inEscape = true;
                }
                if (c == ']' && inEscape == true)
                {
                    inEscape = false;
                }
                if (c == ' ' && inEscape == false)
                {
                    break;
                }
                if (c == '(' && inEscape == false)
                {
                    if (node.Arguments.Substring(index + 1).StartsWith(aliasLabel, StringComparison.InvariantCultureIgnoreCase))
                    {
                        hasAlias        = true;
                        aliasStartIndex = index + aliasLabel.Length + 1;
                    }
                    break;
                }
                sb.Append(c);
            }

            if (hasAlias)
            {
                int    closeParenIndex = node.Arguments.IndexOf(")", aliasStartIndex, StringComparison.InvariantCultureIgnoreCase);
                string aliasName       = node.Arguments.Substring(aliasStartIndex, closeParenIndex - aliasStartIndex);
                sb.Append($" ({aliasName})");
            }

            return(sb.ToString());
        }
Пример #3
0
        private static SqlParseTreeNode ConvertNodeListToTree(List <SqlParseTreeNode> nodeList)
        {
            if (nodeList == null ||
                nodeList.Count == 0)
            {
                return(new SqlParseTreeNode());
            }

            SqlParseTreeNode rootNode     = nodeList[0];
            SqlParseTreeNode previousNode = rootNode;

            for (int nodeIndex = 1; nodeIndex < nodeList.Count; nodeIndex++)
            {
                SqlParseTreeNode node = nodeList[nodeIndex];
                if (node.Level > previousNode.Level)
                {
                    node.Parent = previousNode;
                }
                else if (node.Level == previousNode.Level)
                {
                    // If the previous node is currently considered to be the "root", need to split
                    // the root so that we don't wind up with muliple roots.
                    if (previousNode == rootNode)
                    {
                        rootNode = new SqlParseTreeNode();
                        rootNode.OperationName = string.Empty;
                        previousNode.Parent    = rootNode;
                    }

                    node.Parent = previousNode.Parent;
                }
                else
                {
                    SqlParseTreeNode siblingSearchNode = previousNode.Parent;
                    while (siblingSearchNode != null &&
                           siblingSearchNode.Level > node.Level)
                    {
                        siblingSearchNode = siblingSearchNode.Parent;
                    }

                    if (siblingSearchNode != null)
                    {
                        node.Parent = siblingSearchNode.Parent;
                    }
                }
                if (node.Parent != null)
                {
                    node.Parent.Children.Add(node);
                }

                previousNode = node;
            }

            return(rootNode);
        }
        private static void MeasureNode(SqlParseTreeNode node, int depth, Dictionary <int, int> levelCounts)
        {
            if (levelCounts.ContainsKey(depth) == false)
            {
                levelCounts.Add(depth, 0);
            }
            levelCounts[depth]++;

            foreach (SqlParseTreeNode child in node.Children)
            {
                MeasureNode(child, depth + 1, levelCounts);
            }
        }
        private static string ExtractColumnName(SqlParseTreeNode node)
        {
            string pattern = @"Q?COL:\s+(?<colName>.+)";
            Match  match   = Regex.Match(node.Arguments, pattern);

            if (match.Success)
            {
                string columnName = match.Groups["colName"].Value;
                return(columnName.Trim());
            }

            return("<unknown>");
        }
        public static SqlParseTree Clone(SqlParseTree original)
        {
            if (original == null)
            {
                return(null);
            }

            SqlParseTree tree = new SqlParseTree();

            tree.TreeDescription = original.TreeDescription;
            tree.RootNode        = SqlParseTreeNode.Clone(original.RootNode);
            tree.OuterTreeText   = original.OuterTreeText;
            tree.InnerTreeText   = original.InnerTreeText;
            tree.BeginOffset     = original.BeginOffset;
            tree.EndOffset       = original.EndOffset;

            return(tree);
        }
Пример #7
0
        public static SqlParseTreeNode Clone(SqlParseTreeNode original, SqlParseTreeNode newParent = null)
        {
            if (original == null)
            {
                return(null);
            }

            SqlParseTreeNode node = new SqlParseTreeNode();

            node.SequenceNumber = original.SequenceNumber;
            node.Level          = original.Level;
            node.OperationName  = original.OperationName;
            node.Arguments      = original.Arguments;
            node.Operation      = original.Operation;
            node.Parent         = newParent;
            node.Children       = new List <SqlParseTreeNode>();
            original.Children.ForEach(n => node.Children.Add(SqlParseTreeNode.Clone(n, node)));

            return(node);
        }
        public static string GetLabel(SqlParseTreeNode node)
        {
            if (node.OperationName == "LogOp_Get")
            {
                string tableName = ExtractTableNameAndAlias(node);
                return($"Get {tableName}");
            }

            if (node.OperationName == "ScaOp_Identifier")
            {
                string columnName = ExtractColumnName(node);
                return($"{columnName}");
            }

            if (node.OperationName == "ScaOp_Const")
            {
                string constant = ExtractConstant(node);
                return($"{constant}");
            }

            return(node.OperationName);
        }
Пример #9
0
        private static SqlParseTreeNode ParseSingleNode(string parseLine)
        {
            SqlParseTreeNode node = new SqlParseTreeNode();

            // Determine level by how many tabs prefix the text.
            int spaces = CountLeadingSpaces(parseLine);

            //node.Level = spaces / 4;
            node.Level = spaces;

            // Determine the operation name
            parseLine = parseLine.TrimStart();
            parseLine = FixupLine(parseLine);
            int spaceIndex = parseLine.IndexOfAny(_operatorSeparatorChars);

            if (spaceIndex < 0)
            {
                node.OperationName = parseLine;
                parseLine          = string.Empty;
            }
            else
            {
                node.OperationName = parseLine.Substring(0, spaceIndex);
                parseLine          = parseLine.Substring(spaceIndex).TrimStart();
            }

            OperationType operationType;

            if (Enum.TryParse(node.OperationName, out operationType))
            {
                node.Operation = operationType;
            }

            // Arguments is the remainder
            node.Arguments = parseLine;

            return(node);
        }
Пример #10
0
        public static ReadOnlyCollection <SqlParseTree> Parse(string treeText)
        {
            if (string.IsNullOrEmpty(treeText))
            {
                return(new ReadOnlyCollection <SqlParseTree>(new List <SqlParseTree>()));
            }

            List <SqlParseTree>     trees = new List <SqlParseTree>();
            List <SqlParseTreeNode> nodes = new List <SqlParseTreeNode>();
            SqlParseTree            tree  = null;
            StringBuilder           sb    = new StringBuilder();

            using (StringReader reader = new StringReader(treeText))
            {
                string           line;
                int              lineNumber   = 0;
                SqlParseTreeNode previousNode = null;

                while ((line = reader.ReadLine()) != null)
                {
                    if (line.StartsWith(_endMarker) &&
                        line.StartsWith(_ruleAppliedMarker) == false &&
                        tree != null)
                    {
                        // End of current tree reached.
                        // TODO: determine offset at end
                        tree.EndOffset     = 0;
                        tree.InnerTreeText = sb.ToString();
                    }
                    else if (line.StartsWith(_beginMarker) ||
                             line.StartsWith(_ruleAppliedMarker))
                    {
                        if (tree != null)
                        {
                            tree.RootNode      = ConvertNodeListToTree(nodes);
                            tree.InnerTreeText = sb.ToString();
                            trees.Add(tree);
                            nodes = new List <SqlParseTreeNode>();
                            sb    = new StringBuilder();
                        }
                        tree = new SqlParseTree();
                        tree.OuterTreeText   = treeText;
                        tree.BeginOffset     = 0;
                        tree.TreeDescription = ExtractTreeDescription(line);
                    }
                    else if (line.StartsWith(" ") == false)
                    {
                        //throw new ApplicationException(string.Format("Unknown text {0} in parse tree text (no indentation?)", line));
                    }
                    else
                    {
                        if ((line.Trim().Length > 0 && line.Trim().StartsWith("=") && previousNode != null) ||
                            (previousNode != null && previousNode.OperationName == "Exchange" && previousNode.Arguments == "Partition"))
                        {
                            // Continuation of previous line

                            previousNode.Arguments += line;
                            sb.AppendLine(line);
                        }
                        else
                        {
                            SqlParseTreeNode node = ParseSingleNode(line);
                            node.SequenceNumber = lineNumber;
                            nodes.Add(node);
                            sb.AppendLine(line);
                            previousNode = node;

                            lineNumber++;
                        }
                    }
                }
            }

            if (tree != null)
            {
                tree.RootNode      = ConvertNodeListToTree(nodes);
                tree.EndOffset     = 0;
                tree.InnerTreeText = sb.ToString();
                trees.Add(tree);
            }

            SetTreeOrder(trees);

            return(new ReadOnlyCollection <SqlParseTree>(trees));
        }