├── appveyor.yml ├── .travis.yml ├── sql_profiler ├── Code │ ├── OutputWriter │ │ ├── OutputWriter.cs │ │ ├── HtmlOutputWriter.cs │ │ ├── ConsoleOutputWriter.cs │ │ └── RtfBuilder.cs │ ├── Helpers │ │ ├── PerfColumn.cs │ │ ├── WindowsFix.cs │ │ ├── CommandLineArguments.cs │ │ └── SecretManager.cs │ ├── Lexer │ │ ├── SqlTokens.cs │ │ └── YukonLexer.cs │ ├── SqlServerProfiler.cs │ └── NotImplemented │ │ └── TraceProperties.cs ├── sql_profiler.csproj ├── SQL │ └── Clear_Traces.sql ├── EventList.cs ├── LICENSE.md └── Program.cs ├── sql_profiler.sln ├── .gitattributes ├── README.md └── .gitignore /appveyor.yml: -------------------------------------------------------------------------------- 1 | image: Visual Studio 2017 2 | environment: 3 | DOTNET_CLI_TELEMETRY_OPTOUT: true 4 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 5 | before_build: 6 | - cmd: dotnet restore 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: csharp 3 | dist: xenial 4 | # http://www.erikschierboom.com/2017/03/21/continuous-integration-of-dotnet-core-applications/ 5 | # SDK-version: 6 | dotnet: 2.1.4 7 | mono: none 8 | env: 9 | global: 10 | - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 11 | - DOTNET_CLI_TELEMETRY_OPTOUT: 1 12 | script: 13 | - dotnet restore 14 | - dotnet build 15 | -------------------------------------------------------------------------------- /sql_profiler/Code/OutputWriter/OutputWriter.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace ExpressProfiler 3 | { 4 | 5 | 6 | public abstract class OutputWriter 7 | { 8 | public abstract System.Drawing.Color ForeColor { set; } 9 | public abstract System.Drawing.Color BackColor { set; } 10 | public abstract void AppendLine(); 11 | public abstract void Append(string text); 12 | public new abstract string ToString(); 13 | } 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sql_profiler/Code/Helpers/PerfColumn.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace ExpressProfiler 3 | { 4 | 5 | 6 | public enum HorizontalAlignment 7 | { 8 | Left = 0, 9 | Right = 1, 10 | Center = 2 11 | } 12 | 13 | 14 | public class PerfColumn 15 | { 16 | public string Caption; 17 | public int Column; 18 | public int Width; 19 | public string Format; 20 | public HorizontalAlignment Alignment = HorizontalAlignment.Left; 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sql_profiler/sql_profiler.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | netcoreapp2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /sql_profiler/SQL/Clear_Traces.sql: -------------------------------------------------------------------------------- 1 | 2 | DECLARE @trace_id AS integer; 3 | DECLARE @trace_iterator AS CURSOR; 4 | 5 | SET @trace_iterator = CURSOR FOR 6 | ( 7 | SELECT id FROM sys.traces WHERE is_default <> 1 8 | ); 9 | 10 | 11 | OPEN @trace_iterator; 12 | FETCH NEXT FROM @trace_iterator INTO @trace_id; 13 | 14 | WHILE @@FETCH_STATUS = 0 15 | BEGIN 16 | PRINT 'sp_trace_setstatus ' + CAST(@trace_id AS varchar(20)) + ', 0'; 17 | PRINT 'sp_trace_setstatus ' + CAST(@trace_id AS varchar(20)) + ', 2'; 18 | 19 | -- 0: Stops the specified trace. 20 | -- 1: Starts the specified trace. 21 | -- 2: Closes the specified trace and deletes its definition from the server. 22 | 23 | EXEC sp_trace_setstatus @trace_id, 0; 24 | EXEC sp_trace_setstatus @trace_id, 2; 25 | 26 | FETCH NEXT FROM @trace_iterator INTO @trace_id; 27 | END 28 | 29 | CLOSE @trace_iterator; 30 | DEALLOCATE @trace_iterator; 31 | -------------------------------------------------------------------------------- /sql_profiler.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sql_profiler", "sql_profiler\sql_profiler.csproj", "{337F0509-40BF-4F38-BA9B-F7972E40BED4}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{48DE8B2B-ED7D-42DB-BD6A-01C35D978401}" 9 | ProjectSection(SolutionItems) = preProject 10 | .travis.yml = .travis.yml 11 | appveyor.yml = appveyor.yml 12 | README.md = README.md 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {337F0509-40BF-4F38-BA9B-F7972E40BED4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {337F0509-40BF-4F38-BA9B-F7972E40BED4}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {337F0509-40BF-4F38-BA9B-F7972E40BED4}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {337F0509-40BF-4F38-BA9B-F7972E40BED4}.Release|Any CPU.Build.0 = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | GlobalSection(ExtensibilityGlobals) = postSolution 30 | SolutionGuid = {BF379AE7-8ADA-4F77-8CF2-2DFF82062284} 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /sql_profiler/Code/Helpers/WindowsFix.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace sql_profiler 3 | { 4 | 5 | // https://social.msdn.microsoft.com/Forums/vstudio/en-US/707e9ae1-a53f-4918-8ac4-62a1eddb3c4a/detecting-console-application-exit-in-c?forum=csharpgeneral 6 | internal static class WindowsFix 7 | { 8 | 9 | // An enumerated type for the control messages 10 | // sent to the handler routine. 11 | public enum CtrlTypes 12 | { 13 | CTRL_C_EVENT = 0, 14 | CTRL_BREAK_EVENT, 15 | CTRL_CLOSE_EVENT, 16 | CTRL_LOGOFF_EVENT = 5, 17 | CTRL_SHUTDOWN_EVENT 18 | } 19 | 20 | // A delegate type to be used as the handler routine 21 | // for SetConsoleCtrlHandler. 22 | public delegate bool HandlerRoutine_t(CtrlTypes CtrlType); 23 | 24 | public static void AddConsoleHandler(HandlerRoutine_t on) 25 | { 26 | bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform( 27 | System.Runtime.InteropServices.OSPlatform.Windows 28 | ); 29 | 30 | if(isWindows) 31 | SetConsoleCtrlHandler(on, true); 32 | } 33 | 34 | 35 | private static bool isclosing = false; 36 | 37 | 38 | 39 | 40 | [System.Runtime.InteropServices.DllImport("Kernel32")] 41 | private static extern bool SetConsoleCtrlHandler(HandlerRoutine_t Handler, bool Add); 42 | 43 | private static bool ConsoleCtrlCheck(CtrlTypes ctrlType) 44 | { 45 | System.Console.WriteLine(isclosing); 46 | 47 | // Put your own handler here 48 | switch (ctrlType) 49 | { 50 | case CtrlTypes.CTRL_C_EVENT: 51 | isclosing = true; 52 | System.Console.WriteLine("CTRL+C received!"); 53 | break; 54 | case CtrlTypes.CTRL_BREAK_EVENT: 55 | isclosing = true; 56 | System.Console.WriteLine("CTRL+BREAK received!"); 57 | break; 58 | case CtrlTypes.CTRL_CLOSE_EVENT: 59 | isclosing = true; 60 | System.Console.WriteLine("Program being closed!"); 61 | break; 62 | case CtrlTypes.CTRL_LOGOFF_EVENT: 63 | case CtrlTypes.CTRL_SHUTDOWN_EVENT: 64 | isclosing = true; 65 | System.Console.WriteLine("User is logging off!"); 66 | break; 67 | } 68 | 69 | return true; 70 | } 71 | 72 | 73 | } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /sql_profiler/Code/OutputWriter/HtmlOutputWriter.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace ExpressProfiler 3 | { 4 | 5 | 6 | public class HtmlOutputWriter 7 | : OutputWriter 8 | { 9 | private static System.Collections.Generic.Dictionary< 10 | System.Drawing.Color, System.ConsoleColor> s_colorDict; 11 | 12 | 13 | private System.ConsoleColor m_backupForeground; 14 | private System.ConsoleColor m_backupBackground; 15 | 16 | 17 | static HtmlOutputWriter() 18 | { 19 | s_colorDict = SetupColorDictionary(); 20 | } 21 | 22 | 23 | 24 | public HtmlOutputWriter() 25 | { 26 | this.m_backupForeground = System.Console.ForegroundColor; 27 | this.m_backupBackground = System.Console.BackgroundColor; 28 | } 29 | 30 | 31 | private static System.Collections.Generic.Dictionary< 32 | System.Drawing.Color, System.ConsoleColor> 33 | SetupColorDictionary() 34 | { 35 | System.Collections.Generic.Dictionary 36 | dict = new System.Collections.Generic.Dictionary< 37 | System.Drawing.Color, System.ConsoleColor 38 | >(); 39 | 40 | dict.Add(System.Drawing.Color.Black, System.ConsoleColor.Black); 41 | dict.Add(System.Drawing.Color.DarkBlue, System.ConsoleColor.DarkBlue); 42 | dict.Add(System.Drawing.Color.DarkGreen, System.ConsoleColor.DarkGreen); 43 | dict.Add(System.Drawing.Color.DarkCyan, System.ConsoleColor.DarkCyan); 44 | dict.Add(System.Drawing.Color.DarkRed, System.ConsoleColor.DarkRed); 45 | dict.Add(System.Drawing.Color.DarkMagenta, System.ConsoleColor.DarkMagenta); 46 | dict.Add(System.Drawing.Color.FromArgb(215, 195, 42), System.ConsoleColor.DarkYellow); 47 | dict.Add(System.Drawing.Color.Gray, System.ConsoleColor.Gray); 48 | dict.Add(System.Drawing.Color.DarkGray, System.ConsoleColor.DarkGray); 49 | dict.Add(System.Drawing.Color.Blue, System.ConsoleColor.Blue); 50 | dict.Add(System.Drawing.Color.Green, System.ConsoleColor.Green); 51 | dict.Add(System.Drawing.Color.Cyan, System.ConsoleColor.Cyan); 52 | dict.Add(System.Drawing.Color.Red, System.ConsoleColor.Red); 53 | dict.Add(System.Drawing.Color.Magenta, System.ConsoleColor.Magenta); 54 | dict.Add(System.Drawing.Color.Yellow, System.ConsoleColor.Yellow); 55 | dict.Add(System.Drawing.Color.White, System.ConsoleColor.White); 56 | 57 | return dict; 58 | } 59 | 60 | 61 | public override System.Drawing.Color ForeColor 62 | { 63 | set { System.Console.ForegroundColor = s_colorDict[value]; } 64 | } 65 | 66 | 67 | public override System.Drawing.Color BackColor 68 | { 69 | set 70 | { 71 | System.Console.BackgroundColor = s_colorDict[value]; 72 | System.Console.WriteLine(new string(' ', System.Console.BufferWidth)); 73 | } 74 | } 75 | 76 | 77 | public override void AppendLine() 78 | { 79 | System.Console.WriteLine(); 80 | } 81 | 82 | 83 | public override void Append(string text) 84 | { 85 | System.Console.Write(text); 86 | } 87 | 88 | 89 | public override string ToString() 90 | { 91 | System.Console.ForegroundColor = this.m_backupForeground; 92 | System.Console.BackgroundColor = this.m_backupBackground; 93 | 94 | return ""; 95 | } 96 | 97 | 98 | } 99 | 100 | 101 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # MS-SQL-Server command line profiler ![Travis-CI Status](https://travis-ci.org/ststeiger/sql_profiler.svg?branch=master) ![AppVeyor Status](https://ci.appveyor.com/api/projects/status/2s9x1armpbam5nnx?svg=true) 3 | 4 | 5 | sql_profiler is a simple and fast replacement for SQL Server Profiler.
6 | It's a .NET-Core command-line port of ExpressProfiler, and runs everywhere .NET Core runs. 7 | So it runs on 8 | - Windows (x86-32, x86-64) 9 | - Linux (x86-64, ARM-32) 10 | - Mac/OS-X. 11 | 12 | It's a fork of [ExpressProfiler](https://github.com/OleksiiKovalov/expressprofiler) for MS-SQL-Server ([actually a fork of a slightly modified version](https://github.com/ststeiger/ExpressProfiler) - working datetime-format for any language).
13 | I used it to port ExpressProfiler to .NET Core (command-line). 14 | 15 | 16 | sql_profiler can be used with both Express and non-Express editions of SQL Server 2005/2008/2008r2/2012/2014.
17 | Installation or administrative rights are not required.
18 | Trace permission are required for the SQL-user.
19 | 20 | 21 | **Invocation** 22 | ```bash 23 | ./sql_profiler --server {computername\instance} --username WebAppWebServices --password TOP_SECRET --db "The DB you want to profile"; 24 | ``` 25 | 26 | or from the project: 27 | 28 | ```bash 29 | dotnet run sql_profiler --server {computername\instance} --username WebAppWebServices --password TOP_SECRET --db "The DB you want to profile"; 30 | ``` 31 | If you omit the username, it will attempt to connect with integrated security. 32 | 33 | [![Windows-Console-Profiler: This is Sparta !][1]][1] 34 | 35 | [![Linux-Console-Profiler: This is Sparta !][2]][2] 36 | 37 | 38 | 39 | **Grant rights:** 40 | 41 | 42 | ```sql 43 | 44 | -- To Grant access to a Windows Login 45 | USE Master; 46 | GO 47 | GRANT ALTER TRACE TO [DomainNAME\WindowsLogin] 48 | GO 49 | 50 | -- To Grant access to a SQL Login 51 | USE master; 52 | GO 53 | GRANT ALTER TRACE TO manvendra 54 | GO 55 | 56 | ``` 57 | 58 | [(source)](https://www.mssqltips.com/sqlservertip/3559/how-to-grant-permissions-to-run-sql-server-profiler-for-a-non-system-admin-user/) 59 | 60 | 61 | ### Standalone Building 62 | 63 | **Build for Windows x86-64:** 64 | > dotnet restore -r win-x64
65 | > dotnet build -r win-x64
66 | > dotnet publish -f netcoreapp2.0 -c Release -r win-x64
67 | 68 | **Build for Windows x86-32:** 69 | > dotnet restore -r win-x86
70 | > dotnet build -r win-x86
71 | > dotnet publish -f netcoreapp2.0 -c Release -r win-x86
72 | 73 | 74 | **Build for Linux x86-32:** 75 | > **not supported by framework** 76 | 77 | **Build for Linux x86-64:** 78 | > dotnet restore -r linux-x64
79 | > dotnet build -r linux-x64
80 | > dotnet publish -f netcoreapp2.0 -c Release -r linux-x64
81 | 82 | 83 | **Build for Linux ARM-32 (Raspberry PI/Chromebook/Android):** 84 | > dotnet restore -r linux-arm
85 | > dotnet build -r linux-arm
86 | > dotnet publish -f netcoreapp2.0 -c Release -r linux-arm
87 | 88 | **Build for Linux ARM-64:** 89 | > **not supported by framework** 90 | 91 | 92 | **Build for Mac OSX x86-32:** 93 | > **not supported by framework** 94 | 95 | **Build for Mac OSX x86-64:** 96 | > dotnet restore -r osx-x64
97 | > dotnet build -r osx-x64
98 | > dotnet publish -f netcoreapp2.0 -c Release -r osx-x64
99 | 100 | Mac build requires MacOS >= Sierra (10.12+) 101 | 102 | 103 | 104 | # Future: 105 | **Build for Android (arch?):** 106 | > dotnet restore -r android
107 | > dotnet build -r android
108 | > dotnet publish -f netcoreapp2.0 -c Release -r android
109 | 110 | 111 | [List of RIDs][3] 112 | 113 | 114 | 115 | [1]: https://i.stack.imgur.com/IgYvq.png 116 | [2]: https://i.stack.imgur.com/hEaFY.png 117 | [3]: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog 118 | -------------------------------------------------------------------------------- /sql_profiler/Code/OutputWriter/ConsoleOutputWriter.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace ExpressProfiler 3 | { 4 | 5 | 6 | public class ConsoleOutputWriter 7 | : OutputWriter 8 | { 9 | private static bool s_isWindows; 10 | private static System.Collections.Generic.Dictionary< 11 | System.Drawing.Color, System.ConsoleColor> s_colorDict; 12 | 13 | 14 | private System.ConsoleColor m_backupForeground; 15 | private System.ConsoleColor m_backupBackground; 16 | 17 | 18 | static ConsoleOutputWriter() 19 | { 20 | s_isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform( 21 | System.Runtime.InteropServices.OSPlatform.Windows 22 | ); 23 | 24 | s_colorDict = SetupColorDictionary(); 25 | } 26 | 27 | 28 | 29 | public ConsoleOutputWriter() 30 | { 31 | this.m_backupForeground = System.Console.ForegroundColor; 32 | this.m_backupBackground = System.Console.BackgroundColor; 33 | } 34 | 35 | 36 | private static System.Collections.Generic.Dictionary< 37 | System.Drawing.Color, System.ConsoleColor> 38 | SetupColorDictionary() 39 | { 40 | System.Collections.Generic.Dictionary 41 | dict = new System.Collections.Generic.Dictionary< 42 | System.Drawing.Color, System.ConsoleColor 43 | >(); 44 | 45 | dict.Add(System.Drawing.Color.Black, System.ConsoleColor.Black); 46 | dict.Add(System.Drawing.Color.DarkBlue, System.ConsoleColor.DarkBlue); 47 | dict.Add(System.Drawing.Color.DarkGreen, System.ConsoleColor.DarkGreen); 48 | dict.Add(System.Drawing.Color.DarkCyan, System.ConsoleColor.DarkCyan); 49 | dict.Add(System.Drawing.Color.DarkRed, System.ConsoleColor.DarkRed); 50 | dict.Add(System.Drawing.Color.DarkMagenta, System.ConsoleColor.DarkMagenta); 51 | dict.Add(System.Drawing.Color.FromArgb(215, 195, 42), System.ConsoleColor.DarkYellow); 52 | dict.Add(System.Drawing.Color.Gray, System.ConsoleColor.Gray); 53 | dict.Add(System.Drawing.Color.DarkGray, System.ConsoleColor.DarkGray); 54 | dict.Add(System.Drawing.Color.Blue, System.ConsoleColor.Blue); 55 | dict.Add(System.Drawing.Color.Green, System.ConsoleColor.Green); 56 | dict.Add(System.Drawing.Color.Cyan, System.ConsoleColor.Cyan); 57 | dict.Add(System.Drawing.Color.Red, System.ConsoleColor.Red); 58 | dict.Add(System.Drawing.Color.Magenta, System.ConsoleColor.Magenta); 59 | dict.Add(System.Drawing.Color.Yellow, System.ConsoleColor.Yellow); 60 | dict.Add(System.Drawing.Color.White, System.ConsoleColor.White); 61 | dict.Add(System.Drawing.Color.Fuchsia, System.ConsoleColor.Magenta); // Correct ? 62 | 63 | return dict; 64 | } 65 | 66 | 67 | public override System.Drawing.Color ForeColor 68 | { 69 | 70 | 71 | set 72 | { 73 | // if (!s_colorDict.ContainsKey(value)) System.Console.WriteLine(value); 74 | System.Console.ForegroundColor = s_colorDict[value]; 75 | } 76 | } 77 | 78 | 79 | public override System.Drawing.Color BackColor 80 | { 81 | set 82 | { 83 | // if (!s_colorDict.ContainsKey(value)) System.Console.WriteLine(value); 84 | System.Console.BackgroundColor = s_colorDict[value]; 85 | //this.AppendLine(); 86 | } 87 | } 88 | 89 | 90 | public override void AppendLine() 91 | { 92 | // Finish the line with empty color 93 | System.Console.Write(new string(' ', System.Console.BufferWidth - System.Console.CursorLeft)); 94 | 95 | if(!s_isWindows) 96 | System.Console.Write(System.Environment.NewLine); 97 | //else System.Console.WriteLine(); 98 | } 99 | 100 | 101 | public override void Append(string text) 102 | { 103 | System.Console.Write(text); 104 | } 105 | 106 | 107 | public override string ToString() 108 | { 109 | System.Console.ForegroundColor = this.m_backupForeground; 110 | System.Console.BackgroundColor = this.m_backupBackground; 111 | 112 | return ""; 113 | } 114 | 115 | 116 | } 117 | 118 | 119 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /sql_profiler/Code/OutputWriter/RtfBuilder.cs: -------------------------------------------------------------------------------- 1 | 2 | // Traceutils assembly 3 | // writen by Locky, 2009. 4 | 5 | namespace ExpressProfiler 6 | { 7 | 8 | 9 | class RTFBuilder 10 | : OutputWriter 11 | { 12 | private readonly System.Text.StringBuilder m_Sb = new System.Text.StringBuilder(); 13 | private readonly System.Collections.Generic.List 14 | m_Colortable = new System.Collections.Generic.List(); 15 | private readonly System.Collections.Specialized.StringCollection m_Fonttable = 16 | new System.Collections.Specialized.StringCollection(); 17 | private System.Drawing.Color m_Forecolor; 18 | 19 | public override System.Drawing.Color ForeColor 20 | { 21 | set 22 | { 23 | if (!m_Colortable.Contains(value)) 24 | { 25 | m_Colortable.Add(value); 26 | } 27 | 28 | if (value != m_Forecolor) 29 | { 30 | m_Sb.Append(string.Format("\\cf{0} ", m_Colortable.IndexOf(value) + 1)); 31 | } 32 | 33 | m_Forecolor = value; 34 | } 35 | } 36 | 37 | 38 | private System.Drawing.Color m_Backcolor; 39 | 40 | public override System.Drawing.Color BackColor 41 | { 42 | set 43 | { 44 | if (!m_Colortable.Contains(value)) 45 | { 46 | m_Colortable.Add(value); 47 | } 48 | 49 | if (value != m_Backcolor) 50 | { 51 | m_Sb.Append(string.Format("\\highlight{0} ", m_Colortable.IndexOf(value) + 1)); 52 | } 53 | 54 | m_Backcolor = value; 55 | } 56 | } 57 | 58 | 59 | public RTFBuilder() 60 | { 61 | ForeColor = System.Drawing.Color.Black; // Color.FromKnownColor(KnownColor.WindowText); 62 | BackColor = System.Drawing.Color.White; // Color.FromKnownColor(KnownColor.Window); 63 | m_DefaultFontSize = 20F; 64 | } 65 | 66 | public override void AppendLine() 67 | { 68 | m_Sb.AppendLine("\\line "); 69 | } 70 | 71 | public override void Append(string value) 72 | { 73 | if (!string.IsNullOrEmpty(value)) 74 | { 75 | value = value.Replace("\r\n", "\n"); 76 | 77 | // A sole carriage return should not be treated as Environment.NewLine 78 | value = value.Replace("\r", ""); 79 | value = CheckChar(value); 80 | 81 | int newlineIndex = -1; 82 | while ((newlineIndex = value.IndexOf('\n')) != -1) 83 | { 84 | string valueToAdd = value.Substring(0, newlineIndex); 85 | if (!string.IsNullOrEmpty(valueToAdd)) 86 | m_Sb.Append(valueToAdd); 87 | 88 | m_Sb.Append("\\line "); 89 | 90 | value = value.Substring(newlineIndex + 1); 91 | } // Whend 92 | 93 | if (!string.IsNullOrEmpty(value)) 94 | m_Sb.Append(value); 95 | } 96 | } 97 | 98 | private static readonly char[] Slashable = new[] {'{', '}', '\\'}; 99 | private readonly float m_DefaultFontSize; 100 | 101 | private static string CheckChar(string value) 102 | { 103 | if (!string.IsNullOrEmpty(value)) 104 | { 105 | if (value.IndexOfAny(Slashable) >= 0) 106 | { 107 | // value = value.Replace("{", "\\{").Replace("}", "\\}").Replace("\\", "\\\\"); 108 | value = value.Replace("\\", "\\\\").Replace("{", "\\{").Replace("}", "\\}"); 109 | } 110 | 111 | bool replaceuni = false; 112 | for (int i = 0; i < value.Length; i++) 113 | { 114 | if (value[i] > 255) 115 | { 116 | replaceuni = true; 117 | break; 118 | } 119 | } 120 | 121 | if (replaceuni) 122 | { 123 | System.Text.StringBuilder sb = new System.Text.StringBuilder(); 124 | for (int i = 0; i < value.Length; i++) 125 | { 126 | if (value[i] <= 255) 127 | { 128 | sb.Append(value[i]); 129 | } 130 | else 131 | { 132 | sb.Append("\\u"); 133 | sb.Append((int) value[i]); 134 | sb.Append("?"); 135 | } 136 | } 137 | 138 | value = sb.ToString(); 139 | } 140 | } 141 | 142 | 143 | return value; 144 | } 145 | 146 | public override string ToString() 147 | { 148 | System.Text.StringBuilder result = new System.Text.StringBuilder(); 149 | result.Append("{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang3081"); 150 | result.Append("{\\fonttbl"); 151 | for (int i = 0; i < m_Fonttable.Count; i++) 152 | { 153 | try 154 | { 155 | result.Append(string.Format(m_Fonttable[i], i)); 156 | } 157 | catch (System.Exception ex) 158 | { 159 | System.Console.WriteLine(ex.Message); 160 | } 161 | } 162 | 163 | result.AppendLine("}"); 164 | result.Append("{\\colortbl ;"); 165 | foreach (System.Drawing.Color item in m_Colortable) 166 | { 167 | result.AppendFormat("\\red{0}\\green{1}\\blue{2};", item.R, item.G, item.B); 168 | } 169 | 170 | result.AppendLine("}"); 171 | result.Append("\\viewkind4\\uc1\\pard\\plain\\f0"); 172 | result.AppendFormat("\\fs{0} ", m_DefaultFontSize); 173 | result.AppendLine(); 174 | result.Append(m_Sb.ToString()); 175 | result.Append("}"); 176 | return result.ToString(); 177 | } 178 | 179 | 180 | } 181 | 182 | 183 | } 184 | -------------------------------------------------------------------------------- /sql_profiler/EventList.cs: -------------------------------------------------------------------------------- 1 | 2 | // Traceutils assembly 3 | // writen by Locky, 2009. 4 | 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.IO; 9 | using System.Xml.Serialization; 10 | 11 | 12 | namespace ExpressProfiler 13 | { 14 | 15 | 16 | [Serializable] 17 | public class CEvent 18 | { 19 | // ReSharper disable UnaccessedField.Global 20 | // ReSharper disable FieldCanBeMadeReadOnly.Global 21 | // ReSharper disable InconsistentNaming 22 | // ReSharper disable MemberCanBePrivate.Global 23 | [XmlAttribute] public long EventClass; 24 | [XmlAttribute] public long DatabaseID; 25 | [XmlAttribute] public long ObjectID; 26 | [XmlAttribute] public long RowCounts; 27 | public string TextData; 28 | [XmlAttribute] public string DatabaseName; 29 | [XmlAttribute] public string ObjectName; 30 | 31 | [XmlAttribute] public long Count, CPU, Reads, Writes, Duration, SPID, NestLevel; 32 | // ReSharper restore MemberCanBePrivate.Global 33 | // ReSharper restore InconsistentNaming 34 | // ReSharper restore FieldCanBeMadeReadOnly.Global 35 | // ReSharper restore UnaccessedField.Global 36 | 37 | public long AvgCPU 38 | { 39 | get { return Count == 0 ? 0 : CPU / Count; } 40 | } 41 | 42 | public long AvgReads 43 | { 44 | get { return Count == 0 ? 0 : Reads / Count; } 45 | } 46 | 47 | public long AvgWrites 48 | { 49 | get { return Count == 0 ? 0 : Writes / Count; } 50 | } 51 | 52 | public long AvgDuration 53 | { 54 | get { return Count == 0 ? 0 : Duration / Count; } 55 | } 56 | 57 | 58 | //needed for serialization 59 | // ReSharper disable UnusedMember.Global 60 | public CEvent() 61 | { 62 | } 63 | // ReSharper restore UnusedMember.Global 64 | 65 | public CEvent(long aDatabaseID, string aDatabaseName, long aObjectID, string aObjectName, string aTextData) 66 | { 67 | DatabaseID = aDatabaseID; 68 | DatabaseName = aDatabaseName; 69 | ObjectID = aObjectID; 70 | ObjectName = aObjectName; 71 | TextData = aTextData; 72 | } 73 | 74 | public CEvent(long eventClass, long spid, long nestLevel, long aDatabaseID, string aDatabaseName, 75 | long aObjectID, string aObjectName, string aTextData, long duration, long reads, long writes, long cpu) 76 | { 77 | EventClass = eventClass; 78 | DatabaseID = aDatabaseID; 79 | DatabaseName = aDatabaseName; 80 | ObjectID = aObjectID; 81 | ObjectName = aObjectName; 82 | TextData = aTextData; 83 | Duration = duration; 84 | Reads = reads; 85 | Writes = writes; 86 | CPU = cpu; 87 | SPID = spid; 88 | NestLevel = nestLevel; 89 | } 90 | 91 | public string GetKey() 92 | { 93 | return String.Format("({0}).({1}).({2}).({3})", DatabaseID, ObjectID, ObjectName, TextData); 94 | } 95 | } 96 | 97 | public class SimpleEventList 98 | { 99 | public readonly SortedDictionary List; 100 | 101 | public SimpleEventList() 102 | { 103 | List = new SortedDictionary(); 104 | } 105 | 106 | public void SaveToFile(string filename) 107 | { 108 | CEvent[] a = new CEvent[List.Count]; 109 | List.Values.CopyTo(a, 0); 110 | XmlSerializer x = new XmlSerializer(typeof(CEvent[])); 111 | 112 | FileStream fs = new FileStream(filename, FileMode.Create); 113 | x.Serialize(fs, a); 114 | fs.Dispose(); 115 | } 116 | 117 | public void AddEvent(long eventClass, long nestLevel, long databaseID, string databaseName, long objectID, 118 | string objectName, string textData, long cpu, long reads, long writes, long duration, long count, 119 | long rowcounts) 120 | { 121 | CEvent evt; 122 | string key = String.Format("({0}).({1}).({2})", databaseID, objectID, textData); 123 | if (!List.TryGetValue(key, out evt)) 124 | { 125 | evt = new CEvent(databaseID, databaseName, objectID, objectName, textData); 126 | List.Add(key, evt); 127 | } 128 | 129 | evt.NestLevel = nestLevel; 130 | evt.EventClass = eventClass; 131 | evt.Count += count; 132 | evt.CPU += cpu; 133 | evt.Reads += reads; 134 | evt.Writes += writes; 135 | evt.Duration += duration; 136 | evt.RowCounts += rowcounts; 137 | } 138 | } 139 | 140 | public class CEventList 141 | { 142 | public readonly SortedDictionary EventList; 143 | 144 | public CEventList() 145 | { 146 | EventList = new SortedDictionary(); 147 | } 148 | 149 | public void AppendFromFile(int cnt, string filename, bool ignorenonamesp, bool transform) 150 | { 151 | XmlSerializer x = new XmlSerializer(typeof(CEvent[])); 152 | FileStream fs = new FileStream(filename, FileMode.Open); 153 | CEvent[] a = (CEvent[]) x.Deserialize(fs); 154 | YukonLexer lex = new YukonLexer(); 155 | foreach (CEvent e in a) 156 | { 157 | if (e.TextData.Contains("statman") || e.TextData.Contains("UPDATE STATISTICS")) continue; 158 | if (!ignorenonamesp || e.ObjectName.Length != 0) 159 | { 160 | if (transform) 161 | { 162 | AddEvent(cnt, e.DatabaseID, e.DatabaseName 163 | , e.ObjectName.Length == 0 ? 0 : e.ObjectID 164 | , e.ObjectName.Length == 0 ? "" : e.ObjectName 165 | , e.ObjectName.Length == 0 ? lex.StandardSql(e.TextData) : e.TextData, e.CPU, e.Reads, 166 | e.Writes, e.Duration, e.Count, e.RowCounts); 167 | } 168 | else 169 | { 170 | AddEvent(cnt, e.DatabaseID, e.DatabaseName, e.ObjectID, e.ObjectName, e.TextData, e.CPU, 171 | e.Reads, e.Writes, e.Duration, e.Count, e.RowCounts); 172 | } 173 | } 174 | } 175 | 176 | fs.Dispose(); 177 | } 178 | 179 | public void AddEvent(int cnt, long databaseID, string databaseName, long objectID, string objectName, 180 | string textData, long cpu, long reads, long writes, long duration, long count, long rowcounts) 181 | { 182 | CEvent[] evt; 183 | CEvent e; 184 | string key = String.Format("({0}).({1}).({2}).({3})", databaseID, objectID, objectName, textData); 185 | if (!EventList.TryGetValue(key, out evt)) 186 | { 187 | evt = new CEvent[2]; 188 | for (int k = 0; k < evt.Length; k++) 189 | { 190 | evt[k] = new CEvent(databaseID, databaseName, objectID, objectName, textData); 191 | } 192 | 193 | EventList.Add(key, evt); 194 | e = evt[cnt]; 195 | } 196 | else 197 | { 198 | e = evt[cnt]; 199 | } 200 | 201 | e.Count += count; 202 | e.CPU += cpu; 203 | e.Reads += reads; 204 | e.Writes += writes; 205 | e.Duration += duration; 206 | e.RowCounts += rowcounts; 207 | } 208 | } 209 | } -------------------------------------------------------------------------------- /sql_profiler/Code/Helpers/CommandLineArguments.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace sql_profiler 3 | { 4 | 5 | 6 | /// 7 | /// Arguments class 8 | /// 9 | public class CommandLineArguments 10 | { 11 | 12 | 13 | private System.Collections.Specialized.StringDictionary Parameters; 14 | 15 | 16 | public CommandLineArguments(string[] Args) 17 | : this(Args, null) 18 | { } // End Constructor 19 | 20 | 21 | public CommandLineArguments(string[] Args 22 | , System.Collections.Generic.Dictionary defaultValues) 23 | { 24 | Parameters = new System.Collections.Specialized.StringDictionary(); 25 | System.Text.RegularExpressions.Regex Spliter = 26 | new System.Text.RegularExpressions.Regex(@"^-{1,2}|^/|=|:", 27 | System.Text.RegularExpressions.RegexOptions.IgnoreCase 28 | | System.Text.RegularExpressions.RegexOptions.Compiled 29 | ); 30 | 31 | System.Text.RegularExpressions.Regex Remover = 32 | new System.Text.RegularExpressions.Regex(@"^['""]?(.*?)['""]?$", 33 | System.Text.RegularExpressions.RegexOptions.IgnoreCase 34 | | System.Text.RegularExpressions.RegexOptions.Compiled 35 | ); 36 | 37 | string Parameter = null; 38 | string[] Parts; 39 | 40 | // Valid parameters forms: 41 | // {-,/,--}param{ ,=,:}((",')value(",')) 42 | // Examples: 43 | // -param1 value1 --param2 /param3:"Test-:-work" 44 | // /param4=happy -param5 '--=nice=--' 45 | foreach (string Txt in Args) 46 | { 47 | // Look for new parameters (-,/ or --) and a 48 | // possible enclosed value (=,:) 49 | Parts = Spliter.Split(Txt, 3); 50 | 51 | switch (Parts.Length) 52 | { 53 | // Found a value (for the last parameter 54 | // found (space separator)) 55 | case 1: 56 | if (Parameter != null) 57 | { 58 | if (!Parameters.ContainsKey(Parameter)) 59 | { 60 | Parts[0] = 61 | Remover.Replace(Parts[0], "$1"); 62 | 63 | Parameters.Add(Parameter, Parts[0]); 64 | } 65 | Parameter = null; 66 | } 67 | // else Error: no parameter waiting for a value (skipped) 68 | break; 69 | 70 | // Found just a parameter 71 | case 2: 72 | // The last parameter is still waiting. 73 | // With no value, set it to true. 74 | if (Parameter != null) 75 | { 76 | if (!Parameters.ContainsKey(Parameter)) 77 | Parameters.Add(Parameter, "true"); 78 | } 79 | Parameter = Parts[1]; 80 | break; 81 | 82 | // Parameter with enclosed value 83 | case 3: 84 | // The last parameter is still waiting. 85 | // With no value, set it to true. 86 | if (Parameter != null) 87 | { 88 | if (!Parameters.ContainsKey(Parameter)) 89 | Parameters.Add(Parameter, "true"); 90 | } // End if(Parameter != null) 91 | 92 | Parameter = Parts[1]; 93 | 94 | // Remove possible enclosing characters (",') 95 | if (!Parameters.ContainsKey(Parameter)) 96 | { 97 | Parts[2] = Remover.Replace(Parts[2], "$1"); 98 | Parameters.Add(Parameter, Parts[2]); 99 | } // End if(!Parameters.ContainsKey(Parameter)) 100 | 101 | Parameter = null; 102 | break; 103 | } // End switch(Parts.Length) 104 | 105 | } // Next Txt 106 | 107 | // In case a parameter is still waiting 108 | if (Parameter != null) 109 | { 110 | if (!Parameters.ContainsKey(Parameter)) 111 | Parameters.Add(Parameter, "true"); 112 | } // End if(Parameter != null) 113 | 114 | // Add default values 115 | if (defaultValues != null) 116 | { 117 | foreach (System.Collections.Generic.KeyValuePair kvp in defaultValues) 118 | { 119 | if (!this.Parameters.ContainsKey(kvp.Key)) 120 | this.Parameters[kvp.Key] = kvp.Value; 121 | } // Next kvp 122 | } // End if (defaultValues != null) 123 | 124 | } // End Constructor 125 | 126 | 127 | public int? GetInt(string param) 128 | { 129 | string str = this[param]; 130 | int iValue; 131 | if (int.TryParse(str, out iValue)) 132 | return iValue; 133 | 134 | return null; 135 | } // End Function GetInt 136 | 137 | 138 | public long? GetLong(string param) 139 | { 140 | string str = this[param]; 141 | long lngValue; 142 | if (long.TryParse(str, out lngValue)) 143 | return lngValue; 144 | 145 | return null; 146 | } // End Function GetLong 147 | 148 | 149 | public bool? GetBool(string param) 150 | { 151 | string str = this[param]; 152 | bool bValue; 153 | if (bool.TryParse(str, out bValue)) 154 | return bValue; 155 | 156 | return null; 157 | } // End Function GetBool 158 | 159 | 160 | public T GetValue(string name) 161 | { 162 | System.Type t = typeof(T); 163 | bool nullable = false; 164 | if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(System.Nullable<>)) 165 | { 166 | nullable = true; 167 | t = System.Nullable.GetUnderlyingType(t); 168 | } 169 | 170 | 171 | if (!this.ContainsKey(name)) 172 | return (T)(object)null; 173 | 174 | if (object.ReferenceEquals(t, typeof(string))) 175 | { 176 | return (T)(object)this[name]; 177 | } 178 | 179 | if (object.ReferenceEquals(t, typeof(bool))) 180 | { 181 | bool? val = GetBool(name); 182 | return (T)(object)val; 183 | } 184 | 185 | if (object.ReferenceEquals(t, typeof(int))) 186 | { 187 | int? val = GetInt(name); 188 | return (T)(object)val; 189 | } 190 | 191 | if (object.ReferenceEquals(t, typeof(long))) 192 | { 193 | long? val = GetLong(name); 194 | return (T)(object)val; 195 | } 196 | 197 | throw new System.NotSupportedException($"Type {t.FullName} not supported."); 198 | return (T)(object)null; 199 | } // End Function GetValue 200 | 201 | 202 | // Retrieve a parameter value if it exists 203 | // (overriding C# indexer property) 204 | public string this[string Param] 205 | { 206 | get 207 | { 208 | return (Parameters[Param]); 209 | } 210 | set 211 | { 212 | this.Parameters[Param] = value; 213 | } 214 | } // End Default-Property 215 | 216 | 217 | public bool ContainsKey(string key) 218 | { 219 | return Parameters.ContainsKey(key); 220 | } // End Function ContainsKey 221 | 222 | 223 | } // End Class CommandLineArguments 224 | 225 | 226 | } // End Namespace sql_profiler 227 | -------------------------------------------------------------------------------- /sql_profiler/Code/Lexer/SqlTokens.cs: -------------------------------------------------------------------------------- 1 | 2 | // Traceutils assembly 3 | // writen by Locky, 2009. 4 | 5 | 6 | namespace ExpressProfiler 7 | { 8 | 9 | 10 | class Sqltokens 11 | { 12 | 13 | #region Keywords 14 | private const string Keywords = "ADD,ALTER,AS,ASC,AUTHORIZATION,BACKUP," + 15 | "BEGIN,BREAK,BROWSE,BULK,BY,CASCADE," + 16 | "CHECK,CHECKPOINT,CLOSE,CLUSTERED,COLLATE," + 17 | "COLUMN,COMMIT,COMPUTE,CONSTRAINT,CONTAINS,CONTAINSTABLE," + 18 | "CONTINUE,CREATE,CURRENT,CURSOR,DATABASE," + 19 | "DBCC,DEALLOCATE,DECLARE,DEFAULT,DELETE,DENY,DESC,DISK," + 20 | "DISTINCT,DISTRIBUTED,DOUBLE,DROP,DUMMY,DUMP,ELSE,END," + 21 | "ERRLVL,ESCAPE,EXCEPT,EXEC,EXECUTE,EXIT,FETCH,FILE," + 22 | "FILLFACTOR,FOR,FOREIGN,FORMSOF,FREETEXT,FREETEXTTABLE,FROM,FULL," + 23 | "FUNCTION,GOTO,GRANT,GROUP,HAVING,HOLDLOCK,IDENTITY," + 24 | "IDENTITYCOL,IDENTITY_INSERT,IF,INFLECTIONAL,INDEX,INNER,INSERT," + 25 | "INTERSECT,INTO,IS,ISABOUT,KEY,KILL,LINENO,LOAD," + 26 | "NATIONAL,NOCHECK,NONCLUSTERED,OF,OFF," + 27 | "OFFSETS,ON,OPEN,OPENDATASOURCE,OPENQUERY,OPENROWSET,OPENXML," + 28 | "OPTION,ORDER,OVER,PERCENT,PLAN,PRECISION," + 29 | "PRIMARY,PRINT,PROC,PROCEDURE,PUBLIC,RAISERROR,READ," + 30 | "READTEXT,RECONFIGURE,REFERENCES,REPLICATION,RESTORE," + 31 | "RESTRICT,RETURN,REVOKE,ROLLBACK,ROWCOUNT,ROWGUIDCOL," + 32 | "RULE,SAVE,SCHEMA,SELECT,SET,SETUSER,SHUTDOWN," + 33 | "STATISTICS,TABLE,TEXTSIZE,THEN,TO,TOP,TRAN,TRANSACTION," + 34 | "TRIGGER,TRUNCATE,TSEQUAL,UNION,UNIQUE,UPDATE,UPDATETEXT," + 35 | "USE,VALUES,VARYING,VIEW,WAITFOR,WEIGHT,WHEN,WHERE,WHILE," + 36 | "WITH,WRITETEXT,CURRENT_DATE,CURRENT_TIME" + 37 | ",OUT,NEXT,PRIOR,RETURNS,ABSOLUTE,ACTION,PARTIAL,FALSE" + 38 | ",PREPARE,FIRST,PRIVILEGES,AT,GLOBAL,RELATIVE,ROWS,HOUR,MIN,MAX" + 39 | ",SCROLL,SECOND,SECTION,SIZE,INSENSITIVE,CONNECT,CONNECTION" + 40 | ",ISOLATION,LEVEL,LOCAL,DATE,MINUTE,TRANSLATION" + 41 | ",TRUE,NO,ONLY,WORK,OUTPUT" + 42 | ",ABSOLUTE,ACTION,FREE,PRIOR,PRIVILEGES,AFTER,GLOBAL" + 43 | ",HOUR,RELATIVE,IGNORE,AT,RETURNS,ROLLUP,ROWS,SCROLL" + 44 | ",ISOLATION,SECOND,SECTION,SEQUENCE,LAST,SIZE,LEVEL" + 45 | ",CONNECT,CONNECTION,LOCAL,CUBE,MINUTE,MODIFY,STATIC" + 46 | ",DATE,TEMPORARY,TIME,NEXT,NO,TRANSLATION,TRUE,ONLY" + 47 | ",OUT,DYNAMIC,OUTPUT,PARTIAL,WORK,FALSE,FIRST,PREPARE,GROUPING,FORMAT,INIT,STATS" + 48 | "FORMAT,INIT,STATS,NOCOUNT,FORWARD_ONLY,KEEPFIXED,FORCE,KEEP,MERGE,HASH,LOOP,maxdop,nolock" + 49 | ",updlock,tablock,tablockx,paglock,readcommitted,readpast,readuncommitted,repeatableread,rowlock,serializable,xlock" 50 | + ",delay"; 51 | 52 | #endregion 53 | 54 | 55 | #region Functions 56 | private const string Functions = "@@CONNECTIONS,@@CPU_BUSY,@@CURSOR_ROWS,@@DATEFIRST,@@DBTS,@@ERROR," + 57 | "@@FETCH_STATUS,@@IDENTITY,@@IDLE,@@IO_BUSY,@@LANGID,@@LANGUAGE," + 58 | "@@LOCK_TIMEOUT,@@MAX_CONNECTIONS,@@MAX_PRECISION,@@NESTLEVEL,@@OPTIONS," + 59 | "@@PACKET_ERRORS,@@PACK_RECEIVED,@@PACK_SENT,@@PROCID,@@REMSERVER," + 60 | "@@ROWCOUNT,@@SERVERNAME,@@SERVICENAME,@@SPID,@@TEXTSIZE,@@TIMETICKS," + 61 | "@@TOTAL_ERRORS,@@TOTAL_READ,@@TOTAL_WRITE,@@TRANCOUNT,@@VERSION," + 62 | "ABS,ACOS,APP_NAME,ASCII,ASIN,ATAN,ATN2,AVG,BINARY_CHECKSUM,CAST," + 63 | "CEILING,CHARINDEX,CHECKSUM,CHECKSUM_AGG,COLLATIONPROPERTY," + 64 | "COLUMNPROPERTY,COL_LENGTH,COL_NAME,COS,COT,COUNT," + 65 | "COUNT_BIG," + 66 | "CURSOR_STATUS,DATABASEPROPERTY,DATABASEPROPERTYEX," + 67 | "DATALENGTH,DATEADD,DATEDIFF,DATENAME,DATEPART,DAY,DB_ID,DB_NAME,DEGREES," + 68 | "DIFFERENCE,EXP,FILEGROUPPROPERTY,FILEGROUP_ID,FILEGROUP_NAME,FILEPROPERTY," + 69 | "FILE_ID,FILE_NAME,FLOOR" + 70 | "" + 71 | "FORMATMESSAGE,FULLTEXTCATALOGPROPERTY,FULLTEXTSERVICEPROPERTY," + 72 | "GETANSINULL,GETDATE,GETUTCDATE,HAS_DBACCESS,HOST_ID,HOST_NAME," + 73 | "IDENT_CURRENT,IDENT_INCR,IDENT_SEED,INDEXKEY_PROPERTY,INDEXPROPERTY," + 74 | "INDEX_COL,ISDATE,ISNULL,ISNUMERIC,IS_MEMBER,IS_SRVROLEMEMBER,LEN,LOG," + 75 | "LOG10,LOWER,LTRIM,MONTH,NEWID,OBJECTPROPERTY,OBJECT_ID," + 76 | "OBJECT_NAME,PARSENAME,PATINDEX," + 77 | "PERMISSIONS,PI,POWER,QUOTENAME,RADIANS,RAND,REPLACE,REPLICATE,REVERSE," + 78 | "ROUND,ROWCOUNT_BIG,RTRIM,SCOPE_IDENTITY,SERVERPROPERTY,SESSIONPROPERTY," + 79 | "SIGN,SIN,SOUNDEX,SPACE,SQL_VARIANT_PROPERTY,SQRT,SQUARE," + 80 | "STATS_DATE,STDEV,STDEVP,STR,STUFF,SUBSTRING,SUM,SUSER_SID,SUSER_SNAME," + 81 | "TAN,TEXTPTR,TEXTVALID,TYPEPROPERTY,UNICODE,UPPER," + 82 | "USER_ID,USER_NAME,VAR,VARP,YEAR"; 83 | 84 | #endregion 85 | #region Types 86 | private const string Types = "bigint,binary,bit,char,character,datetime," + 87 | "dec,decimal,float,image,int," + 88 | "integer,money,nchar,ntext,nvarchar,real," + 89 | "rowversion,smalldatetime,smallint,smallmoney," + 90 | "sql_variant,sysname,text,timestamp,tinyint,uniqueidentifier," + 91 | "varbinary,varchar,NUMERIC"; 92 | #endregion 93 | 94 | private const string Greykeywords = "AND,EXISTS,ALL,ANY,BETWEEN,IN,SOME,JOIN,CROSS,OR,NULL,OUTER,NOT,LIKE"; 95 | private const string Fukeywords = "CASE,RIGHT,COALESCE,SESSION_USER,CONVERT,SYSTEM_USER,LEFT,CURRENT_TIMESTAMP,CURRENT_USER,NULLIF,USER"; 96 | 97 | private readonly System.Collections.Generic.Dictionary 98 | m_Words = new System.Collections.Generic 99 | .Dictionary(); 100 | 101 | public YukonLexer.TokenKind this[string token] { get { token = token.ToLower(); return m_Words.ContainsKey(token) ? m_Words[token] : YukonLexer.TokenKind.tkUnknown; } } 102 | 103 | 104 | private void AddTokens(string tokens, YukonLexer.TokenKind tokenkind) 105 | { 106 | System.Text.StringBuilder curtoken = new System.Text.StringBuilder(); 107 | for (int i = 0; i < tokens.Length; i++) 108 | { 109 | if (tokens[i] == ',') 110 | { 111 | string s = curtoken.ToString().ToLower(); 112 | if (!m_Words.ContainsKey(s)) 113 | m_Words.Add(s, tokenkind); 114 | curtoken = new System.Text.StringBuilder(); 115 | } 116 | else 117 | { 118 | curtoken.Append(tokens[i]); 119 | } 120 | } 121 | if (curtoken.Length != 0) m_Words.Add(curtoken.ToString(), tokenkind); 122 | } 123 | 124 | 125 | public Sqltokens() 126 | { 127 | AddTokens(Keywords, YukonLexer.TokenKind.tkKey); 128 | AddTokens(Functions, YukonLexer.TokenKind.tkFunction); 129 | AddTokens(Types, YukonLexer.TokenKind.tkDatatype); 130 | AddTokens(Greykeywords, YukonLexer.TokenKind.tkGreyKeyword); 131 | AddTokens(Fukeywords, YukonLexer.TokenKind.tkFuKeyword); 132 | } 133 | 134 | 135 | } 136 | 137 | 138 | } -------------------------------------------------------------------------------- /sql_profiler/Code/Helpers/SecretManager.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace TestPlotly 3 | { 4 | 5 | 6 | public class SecretManager 7 | { 8 | 9 | // TestPlotly.SecretManager.GetSecret("DefaultDbPassword") 10 | // TestPlotly.SecretManager.GetSecret("GoogleGeoCodingApiKey") 11 | public static T GetSecret(string secretName) 12 | { 13 | string asmName = typeof(SecretManager).Assembly.FullName; 14 | 15 | int ipos = asmName.IndexOf(','); 16 | if (ipos != -1) 17 | { 18 | asmName = asmName.Substring(0, ipos); 19 | } 20 | 21 | return GetSecret(secretName, asmName); 22 | } // End Function GetSecret 23 | 24 | 25 | public static T GetSecret(string secretName, string asmName) 26 | { 27 | T obj = default(T); 28 | 29 | if (System.Environment.OSVersion.Platform == System.PlatformID.Unix) 30 | { 31 | obj = SecretManagerHelper.GetEtcKey("/etc/COR/" + asmName, secretName); 32 | if(obj == null) 33 | obj = SecretManagerHelper.GetEtcKey(@"/etc/COR/All", secretName); 34 | } 35 | else 36 | { 37 | obj = SecretManagerHelper.GetRegistryKey(@"Software\COR\" + asmName, secretName); 38 | if(obj == null) 39 | obj = SecretManagerHelper.GetRegistryKey(@"Software\COR\All", secretName); 40 | } 41 | 42 | return obj; 43 | } // End Function GetSecret 44 | 45 | 46 | } // End Class SecretManager 47 | 48 | 49 | public class SecretManagerHelper 50 | { 51 | 52 | 53 | public static T GetRegistryKey(string key, string value) 54 | { 55 | object obj = GetRegistryKey(key, value); 56 | return ObjectToGeneric(obj); 57 | } // End Function GetRegistryKey 58 | 59 | 60 | public static T GetEtcKey(string path, string value) 61 | { 62 | string obj = null; 63 | 64 | string p = System.IO.Path.Combine(path, value); 65 | if(System.IO.File.Exists(p)) 66 | obj = System.IO.File.ReadAllText(p, System.Text.Encoding.Default); 67 | 68 | if(obj == null) 69 | return ObjectToGeneric((object)obj); 70 | 71 | // || obj.EndsWith(" ") || obj.EndsWith("\t") 72 | while ( obj.EndsWith("\r") || obj.EndsWith("\n") ) 73 | obj = obj.Substring(0, obj.Length - 1); 74 | 75 | return ObjectToGeneric((object)obj); 76 | } // End Function GetRegistryKey 77 | 78 | 79 | private static object GetRegistryKey(string key, string value) 80 | { 81 | object objReturnValue = null; 82 | // HKEY_CURRENT_USER 83 | 84 | //using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine 85 | using (Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.CurrentUser 86 | .OpenSubKey(key)) 87 | { 88 | if (regKey != null) 89 | { 90 | objReturnValue = regKey.GetValue(value); 91 | } // End if (regKey != null) 92 | 93 | } // End Using regKey 94 | 95 | return objReturnValue; 96 | } // End Function GetRegistryKey 97 | 98 | 99 | private static T InlineTypeAssignHelper(object UTO) 100 | { 101 | if (UTO == null) 102 | { 103 | T NullSubstitute = default(T); 104 | return NullSubstitute; 105 | } // End if (UTO == null) 106 | 107 | return (T)UTO; 108 | } // End Template InlineTypeAssignHelper 109 | 110 | 111 | private static T ObjectToGeneric(object objReturnValue) 112 | { 113 | string strReturnValue = null; 114 | System.Type tReturnType = typeof(T); 115 | 116 | if (!object.ReferenceEquals(tReturnType, typeof(System.Byte[]))) 117 | { 118 | if(objReturnValue != null) 119 | strReturnValue = System.Convert.ToString(objReturnValue); 120 | } // End if (!object.ReferenceEquals(tReturnType, typeof(System.Byte[]))) 121 | 122 | try 123 | { 124 | 125 | if (object.ReferenceEquals(tReturnType, typeof(object))) 126 | { 127 | return InlineTypeAssignHelper(objReturnValue); 128 | } 129 | else if (object.ReferenceEquals(tReturnType, typeof(string))) 130 | { 131 | return InlineTypeAssignHelper(strReturnValue); 132 | } // End if string 133 | else if (object.ReferenceEquals(tReturnType, typeof(bool))) 134 | { 135 | bool bReturnValue = false; 136 | bool bSuccess = bool.TryParse(strReturnValue, out bReturnValue); 137 | 138 | if (bSuccess) 139 | return InlineTypeAssignHelper(bReturnValue); 140 | 141 | if (strReturnValue == "0") 142 | return InlineTypeAssignHelper(false); 143 | 144 | return InlineTypeAssignHelper(true); 145 | } // End if bool 146 | else if (object.ReferenceEquals(tReturnType, typeof(int))) 147 | { 148 | int iReturnValue = int.Parse(strReturnValue); 149 | return InlineTypeAssignHelper(iReturnValue); 150 | } // End if int 151 | else if (object.ReferenceEquals(tReturnType, typeof(uint))) 152 | { 153 | uint uiReturnValue = uint.Parse(strReturnValue); 154 | return InlineTypeAssignHelper(uiReturnValue); 155 | } // End if uint 156 | else if (object.ReferenceEquals(tReturnType, typeof(long))) 157 | { 158 | long lngReturnValue = long.Parse(strReturnValue); 159 | return InlineTypeAssignHelper(lngReturnValue); 160 | } // End if long 161 | else if (object.ReferenceEquals(tReturnType, typeof(ulong))) 162 | { 163 | ulong ulngReturnValue = ulong.Parse(strReturnValue); 164 | return InlineTypeAssignHelper(ulngReturnValue); 165 | } // End if ulong 166 | else if (object.ReferenceEquals(tReturnType, typeof(float))) 167 | { 168 | float fltReturnValue = float.Parse(strReturnValue); 169 | return InlineTypeAssignHelper(fltReturnValue); 170 | } 171 | else if (object.ReferenceEquals(tReturnType, typeof(double))) 172 | { 173 | double dblReturnValue = double.Parse(strReturnValue); 174 | return InlineTypeAssignHelper(dblReturnValue); 175 | } 176 | else if (object.ReferenceEquals(tReturnType, typeof(System.Net.IPAddress))) 177 | { 178 | System.Net.IPAddress ipaAddress = null; 179 | 180 | if (string.IsNullOrEmpty(strReturnValue)) 181 | return InlineTypeAssignHelper(ipaAddress); 182 | 183 | ipaAddress = System.Net.IPAddress.Parse(strReturnValue); 184 | return InlineTypeAssignHelper(ipaAddress); 185 | } // End if IPAddress 186 | else if (object.ReferenceEquals(tReturnType, typeof(System.Byte[]))) 187 | { 188 | if (objReturnValue == System.DBNull.Value) 189 | return InlineTypeAssignHelper(null); 190 | 191 | return InlineTypeAssignHelper(objReturnValue); 192 | } 193 | else if (object.ReferenceEquals(tReturnType, typeof(System.Guid))) 194 | { 195 | if (string.IsNullOrEmpty(strReturnValue)) return InlineTypeAssignHelper(null); 196 | 197 | return InlineTypeAssignHelper(new System.Guid(strReturnValue)); 198 | } // End if GUID 199 | else if (object.ReferenceEquals(tReturnType, typeof(System.DateTime))) 200 | { 201 | System.DateTime bReturnValue = System.DateTime.Now; 202 | bool bSuccess = System.DateTime.TryParse(strReturnValue, out bReturnValue); 203 | 204 | if (bSuccess) 205 | return InlineTypeAssignHelper(bReturnValue); 206 | 207 | if (strReturnValue == "0") 208 | return InlineTypeAssignHelper(false); 209 | 210 | return InlineTypeAssignHelper(true); 211 | } // End if datetime 212 | else // No datatype matches 213 | { 214 | throw new System.NotImplementedException("ExecuteScalar: This type is not yet defined."); 215 | } // End else of if tReturnType = datatype 216 | 217 | } // End Try 218 | catch (System.Exception ex) 219 | { 220 | throw; 221 | } // End Catch 222 | 223 | return InlineTypeAssignHelper(null); 224 | } // End Function ObjectToGeneric 225 | 226 | 227 | } // End Class SecretManager 228 | 229 | 230 | } // End Namespace 231 | -------------------------------------------------------------------------------- /sql_profiler/LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | Original code by 3 | https://github.com/OleksiiKovalov/expressprofiler 4 | (no license) 5 | 6 | 7 | All other code 8 | Apache License V2 9 | 10 | 11 | 12 | 13 | Apache License 14 | Version 2.0, January 2004 15 | http://www.apache.org/licenses/ 16 | 17 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 18 | 19 | 1. Definitions. 20 | 21 | "License" shall mean the terms and conditions for use, reproduction, 22 | and distribution as defined by Sections 1 through 9 of this document. 23 | 24 | "Licensor" shall mean the copyright owner or entity authorized by 25 | the copyright owner that is granting the License. 26 | 27 | "Legal Entity" shall mean the union of the acting entity and all 28 | other entities that control, are controlled by, or are under common 29 | control with that entity. For the purposes of this definition, 30 | "control" means (i) the power, direct or indirect, to cause the 31 | direction or management of such entity, whether by contract or 32 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 33 | outstanding shares, or (iii) beneficial ownership of such entity. 34 | 35 | "You" (or "Your") shall mean an individual or Legal Entity 36 | exercising permissions granted by this License. 37 | 38 | "Source" form shall mean the preferred form for making modifications, 39 | including but not limited to software source code, documentation 40 | source, and configuration files. 41 | 42 | "Object" form shall mean any form resulting from mechanical 43 | transformation or translation of a Source form, including but 44 | not limited to compiled object code, generated documentation, 45 | and conversions to other media types. 46 | 47 | "Work" shall mean the work of authorship, whether in Source or 48 | Object form, made available under the License, as indicated by a 49 | copyright notice that is included in or attached to the work 50 | (an example is provided in the Appendix below). 51 | 52 | "Derivative Works" shall mean any work, whether in Source or Object 53 | form, that is based on (or derived from) the Work and for which the 54 | editorial revisions, annotations, elaborations, or other modifications 55 | represent, as a whole, an original work of authorship. For the purposes 56 | of this License, Derivative Works shall not include works that remain 57 | separable from, or merely link (or bind by name) to the interfaces of, 58 | the Work and Derivative Works thereof. 59 | 60 | "Contribution" shall mean any work of authorship, including 61 | the original version of the Work and any modifications or additions 62 | to that Work or Derivative Works thereof, that is intentionally 63 | submitted to Licensor for inclusion in the Work by the copyright owner 64 | or by an individual or Legal Entity authorized to submit on behalf of 65 | the copyright owner. For the purposes of this definition, "submitted" 66 | means any form of electronic, verbal, or written communication sent 67 | to the Licensor or its representatives, including but not limited to 68 | communication on electronic mailing lists, source code control systems, 69 | and issue tracking systems that are managed by, or on behalf of, the 70 | Licensor for the purpose of discussing and improving the Work, but 71 | excluding communication that is conspicuously marked or otherwise 72 | designated in writing by the copyright owner as "Not a Contribution." 73 | 74 | "Contributor" shall mean Licensor and any individual or Legal Entity 75 | on behalf of whom a Contribution has been received by Licensor and 76 | subsequently incorporated within the Work. 77 | 78 | 2. Grant of Copyright License. Subject to the terms and conditions of 79 | this License, each Contributor hereby grants to You a perpetual, 80 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 81 | copyright license to reproduce, prepare Derivative Works of, 82 | publicly display, publicly perform, sublicense, and distribute the 83 | Work and such Derivative Works in Source or Object form. 84 | 85 | 3. Grant of Patent License. Subject to the terms and conditions of 86 | this License, each Contributor hereby grants to You a perpetual, 87 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 88 | (except as stated in this section) patent license to make, have made, 89 | use, offer to sell, sell, import, and otherwise transfer the Work, 90 | where such license applies only to those patent claims licensable 91 | by such Contributor that are necessarily infringed by their 92 | Contribution(s) alone or by combination of their Contribution(s) 93 | with the Work to which such Contribution(s) was submitted. If You 94 | institute patent litigation against any entity (including a 95 | cross-claim or counterclaim in a lawsuit) alleging that the Work 96 | or a Contribution incorporated within the Work constitutes direct 97 | or contributory patent infringement, then any patent licenses 98 | granted to You under this License for that Work shall terminate 99 | as of the date such litigation is filed. 100 | 101 | 4. Redistribution. You may reproduce and distribute copies of the 102 | Work or Derivative Works thereof in any medium, with or without 103 | modifications, and in Source or Object form, provided that You 104 | meet the following conditions: 105 | 106 | (a) You must give any other recipients of the Work or 107 | Derivative Works a copy of this License; and 108 | 109 | (b) You must cause any modified files to carry prominent notices 110 | stating that You changed the files; and 111 | 112 | (c) You must retain, in the Source form of any Derivative Works 113 | that You distribute, all copyright, patent, trademark, and 114 | attribution notices from the Source form of the Work, 115 | excluding those notices that do not pertain to any part of 116 | the Derivative Works; and 117 | 118 | (d) If the Work includes a "NOTICE" text file as part of its 119 | distribution, then any Derivative Works that You distribute must 120 | include a readable copy of the attribution notices contained 121 | within such NOTICE file, excluding those notices that do not 122 | pertain to any part of the Derivative Works, in at least one 123 | of the following places: within a NOTICE text file distributed 124 | as part of the Derivative Works; within the Source form or 125 | documentation, if provided along with the Derivative Works; or, 126 | within a display generated by the Derivative Works, if and 127 | wherever such third-party notices normally appear. The contents 128 | of the NOTICE file are for informational purposes only and 129 | do not modify the License. You may add Your own attribution 130 | notices within Derivative Works that You distribute, alongside 131 | or as an addendum to the NOTICE text from the Work, provided 132 | that such additional attribution notices cannot be construed 133 | as modifying the License. 134 | 135 | You may add Your own copyright statement to Your modifications and 136 | may provide additional or different license terms and conditions 137 | for use, reproduction, or distribution of Your modifications, or 138 | for any such Derivative Works as a whole, provided Your use, 139 | reproduction, and distribution of the Work otherwise complies with 140 | the conditions stated in this License. 141 | 142 | 5. Submission of Contributions. Unless You explicitly state otherwise, 143 | any Contribution intentionally submitted for inclusion in the Work 144 | by You to the Licensor shall be under the terms and conditions of 145 | this License, without any additional terms or conditions. 146 | Notwithstanding the above, nothing herein shall supersede or modify 147 | the terms of any separate license agreement you may have executed 148 | with Licensor regarding such Contributions. 149 | 150 | 6. Trademarks. This License does not grant permission to use the trade 151 | names, trademarks, service marks, or product names of the Licensor, 152 | except as required for reasonable and customary use in describing the 153 | origin of the Work and reproducing the content of the NOTICE file. 154 | 155 | 7. Disclaimer of Warranty. Unless required by applicable law or 156 | agreed to in writing, Licensor provides the Work (and each 157 | Contributor provides its Contributions) on an "AS IS" BASIS, 158 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 159 | implied, including, without limitation, any warranties or conditions 160 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 161 | PARTICULAR PURPOSE. You are solely responsible for determining the 162 | appropriateness of using or redistributing the Work and assume any 163 | risks associated with Your exercise of permissions under this License. 164 | 165 | 8. Limitation of Liability. In no event and under no legal theory, 166 | whether in tort (including negligence), contract, or otherwise, 167 | unless required by applicable law (such as deliberate and grossly 168 | negligent acts) or agreed to in writing, shall any Contributor be 169 | liable to You for damages, including any direct, indirect, special, 170 | incidental, or consequential damages of any character arising as a 171 | result of this License or out of the use or inability to use the 172 | Work (including but not limited to damages for loss of goodwill, 173 | work stoppage, computer failure or malfunction, or any and all 174 | other commercial damages or losses), even if such Contributor 175 | has been advised of the possibility of such damages. 176 | 177 | 9. Accepting Warranty or Additional Liability. While redistributing 178 | the Work or Derivative Works thereof, You may choose to offer, 179 | and charge a fee for, acceptance of support, warranty, indemnity, 180 | or other liability obligations and/or rights consistent with this 181 | License. However, in accepting such obligations, You may act only 182 | on Your own behalf and on Your sole responsibility, not on behalf 183 | of any other Contributor, and only if You agree to indemnify, 184 | defend, and hold each Contributor harmless for any liability 185 | incurred by, or claims asserted against, such Contributor by reason 186 | of your accepting any such warranty or additional liability. 187 | 188 | END OF TERMS AND CONDITIONS 189 | 190 | APPENDIX: How to apply the Apache License to your work. 191 | 192 | To apply the Apache License to your work, attach the following 193 | boilerplate notice, with the fields enclosed by brackets "[]" 194 | replaced with your own identifying information. (Don't include 195 | the brackets!) The text should be enclosed in the appropriate 196 | comment syntax for the file format. We also recommend that a 197 | file or class name and description of purpose be included on the 198 | same "printed page" as the copyright notice for easier 199 | identification within third-party archives. 200 | 201 | Copyright [yyyy] [name of copyright owner] 202 | 203 | Licensed under the Apache License, Version 2.0 (the "License"); 204 | you may not use this file except in compliance with the License. 205 | You may obtain a copy of the License at 206 | 207 | http://www.apache.org/licenses/LICENSE-2.0 208 | 209 | Unless required by applicable law or agreed to in writing, software 210 | distributed under the License is distributed on an "AS IS" BASIS, 211 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 212 | See the License for the specific language governing permissions and 213 | limitations under the License. 214 | -------------------------------------------------------------------------------- /sql_profiler/Code/Lexer/YukonLexer.cs: -------------------------------------------------------------------------------- 1 | 2 | // Traceutils assembly 3 | // writen by Locky, 2009. 4 | 5 | 6 | namespace ExpressProfiler 7 | { 8 | 9 | 10 | public class YukonLexer 11 | { 12 | 13 | public enum TokenKind 14 | { 15 | tkComment, tkDatatype, 16 | tkFunction, tkIdentifier, tkKey, tkNull, tkNumber, tkSpace, tkString, tkSymbol, tkUnknown, tkVariable, tkGreyKeyword, tkFuKeyword 17 | } 18 | 19 | private enum SqlRange { rsUnknown, rsComment, rsString } 20 | private readonly Sqltokens m_Tokens = new Sqltokens(); 21 | 22 | 23 | const string IdentifierStr = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890_#$"; 24 | private readonly char[] m_IdentifiersArray = IdentifierStr.ToCharArray(); 25 | const string HexDigits = "1234567890abcdefABCDEF"; 26 | const string NumberStr = "1234567890.-"; 27 | private int m_StringLen; 28 | private int m_TokenPos; 29 | private string m_Token = ""; 30 | private TokenKind m_TokenId; 31 | private string m_Line; 32 | private int m_Run; 33 | 34 | 35 | private TokenKind TokenId 36 | { 37 | get { return m_TokenId; } 38 | } 39 | 40 | 41 | private string Token { get { /*int len = m_Run - m_TokenPos; return m_Line.Substring(m_TokenPos, len);*/return m_Token; } } 42 | private SqlRange Range { get; set; } 43 | 44 | 45 | 46 | public YukonLexer() 47 | { 48 | System.Array.Sort(m_IdentifiersArray); 49 | } // End Constructor 50 | 51 | 52 | private char GetChar(int idx) 53 | { 54 | return idx >= m_Line.Length ? '\x00' : m_Line[idx]; 55 | } 56 | 57 | 58 | public string StandardSql(string sql) 59 | { 60 | System.Text.StringBuilder result = new System.Text.StringBuilder(); 61 | Line = sql; 62 | while (TokenId != TokenKind.tkNull) 63 | { 64 | switch (TokenId) 65 | { 66 | case TokenKind.tkNumber: 67 | case TokenKind.tkString: result.Append(""); break; 68 | default: result.Append(Token); break; 69 | } 70 | Next(); 71 | } 72 | return result.ToString(); 73 | } 74 | 75 | 76 | public string SyntaxHighlight(OutputWriter sb, string value) 77 | { 78 | Line = value; 79 | 80 | sb.AppendLine(); 81 | 82 | System.Collections.Generic.List lsTokenTypeHistory = 83 | new System.Collections.Generic.List(); 84 | 85 | while (TokenId != TokenKind.tkNull) 86 | { 87 | if (TokenId != TokenKind.tkSpace) 88 | lsTokenTypeHistory.Add(TokenId); 89 | 90 | System.Drawing.Color forecolor; 91 | switch (TokenId) 92 | { 93 | case TokenKind.tkKey: 94 | forecolor = System.Drawing.Color.Blue; 95 | break; 96 | case TokenKind.tkFunction: forecolor = System.Drawing.Color.Fuchsia; break; 97 | case TokenKind.tkGreyKeyword: forecolor = System.Drawing.Color.Gray; break; 98 | case TokenKind.tkFuKeyword: forecolor = System.Drawing.Color.Fuchsia; break; 99 | case TokenKind.tkDatatype: 100 | forecolor = System.Drawing.Color.Blue; break; 101 | case TokenKind.tkNumber: forecolor = System.Drawing.Color.Red; break; 102 | case TokenKind.tkString: forecolor = System.Drawing.Color.Red; break; 103 | case TokenKind.tkComment: 104 | forecolor = System.Drawing.Color.DarkGreen; 105 | break; 106 | default: forecolor = System.Drawing.Color.Black; break; 107 | } 108 | sb.ForeColor = forecolor; 109 | 110 | if (Token == System.Environment.NewLine || Token == "\n") 111 | { 112 | sb.AppendLine(); 113 | } 114 | else if(Token != "\r") 115 | { 116 | int cntHistory = lsTokenTypeHistory.Count; 117 | 118 | // If the token has a datetime parameter-value that is passed as string, 119 | // ensure yyyy-MM-dd' 'HH:mm:ss[.fff] is replaced with yyyy-MM-dd'T'HH:mm:ss[.fff] 120 | if (TokenKind.tkString == TokenId 121 | && cntHistory > 3 122 | && lsTokenTypeHistory[cntHistory - 2] == TokenKind.tkSymbol 123 | && lsTokenTypeHistory[cntHistory - 3] == TokenKind.tkVariable 124 | && System.Text.RegularExpressions.Regex 125 | .IsMatch( 126 | Token 127 | , @"^'\d\d\d\d-\d\d-\d\d\s\d\d\:\d\d\:\d\d(\.\d\d\d)?'$" 128 | , System.Text.RegularExpressions.RegexOptions.Compiled 129 | ) 130 | ) 131 | { 132 | // System.DateTime dt; 133 | // if (System.DateTime.TryParseExact(Token, "yyyy-MM-dd HH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AllowWhiteSpaces, out dt)) 134 | // sb.Append(dt.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff")); 135 | sb.Append(Token.Replace(" ", "T")); 136 | } 137 | else 138 | sb.Append(Token); 139 | } 140 | Next(); 141 | } 142 | 143 | sb.AppendLine(); 144 | sb.AppendLine(); 145 | 146 | lsTokenTypeHistory.Clear(); 147 | lsTokenTypeHistory = null; 148 | 149 | return sb.ToString(); 150 | } 151 | 152 | private string Line 153 | { 154 | set { Range = SqlRange.rsUnknown; m_Line = value; m_Run = 0; Next(); } 155 | } 156 | private void NullProc() { m_TokenId = TokenKind.tkNull; } 157 | // ReSharper disable InconsistentNaming 158 | private void LFProc() { m_TokenId = TokenKind.tkSpace; m_Run++; } 159 | private void CRProc() { m_TokenId = TokenKind.tkSpace; m_Run++; if (GetChar(m_Run) == '\x0A') m_Run++; } 160 | // ReSharper restore InconsistentNaming 161 | 162 | private void AnsiCProc() 163 | { 164 | switch (GetChar(m_Run)) 165 | { 166 | case '\x00': NullProc(); break; 167 | case '\x0A': LFProc(); break; 168 | case '\x0D': CRProc(); break; 169 | 170 | default: 171 | { 172 | m_TokenId = TokenKind.tkComment; 173 | char c; 174 | do 175 | { 176 | if (GetChar(m_Run) == '*' && GetChar(m_Run + 1) == '/') 177 | { 178 | Range = SqlRange.rsUnknown; m_Run += 2; break; 179 | } 180 | m_Run++; 181 | c = GetChar(m_Run); 182 | } 183 | while (!(c == '\x00' || c == '\x0A' || c == '\x0D')); 184 | break; 185 | } 186 | 187 | 188 | 189 | } 190 | } 191 | 192 | private void AsciiCharProc() 193 | { 194 | if (GetChar(m_Run) == '\x00') { NullProc(); } 195 | else 196 | { 197 | m_TokenId = TokenKind.tkString; 198 | if (m_Run > 0 || Range != SqlRange.rsString || GetChar(m_Run) != '\x27') 199 | { 200 | Range = SqlRange.rsString; 201 | char c; 202 | do { m_Run++; c = GetChar(m_Run); } while (!(c == '\x00' || c == '\x0A' || c == '\x0D' || c == '\x27')); 203 | if (GetChar(m_Run) == '\x27') 204 | { 205 | m_Run++; 206 | Range = SqlRange.rsUnknown; 207 | } 208 | } 209 | } 210 | } 211 | 212 | private void DoProcTable(char chr) 213 | { 214 | switch (chr) 215 | { 216 | case '\x00': NullProc(); break; 217 | case '\x0A': LFProc(); break; 218 | case '\x0D': CRProc(); break; 219 | case '\x27': AsciiCharProc(); break; 220 | 221 | case '=': EqualProc(); break; 222 | case '>': GreaterProc(); break; 223 | case '<': LowerProc(); break; 224 | case '-': MinusProc(); break; 225 | case '|': OrSymbolProc(); break; 226 | case '+': PlusProc(); break; 227 | case '/': SlashProc(); break; 228 | case '&': AndSymbolProc(); break; 229 | case '\x22': QuoteProc(); break; 230 | case ':': 231 | case '@': VariableProc(); break; 232 | case '^': 233 | case '%': 234 | case '*': 235 | case '!': SymbolAssignProc(); break; 236 | case '{': 237 | case '}': 238 | case '.': 239 | case ',': 240 | case ';': 241 | case '?': 242 | case '(': 243 | case ')': 244 | case ']': 245 | case '~': SymbolProc(); break; 246 | case '[': BracketProc(); break; 247 | default: 248 | DoInsideProc(chr); break; 249 | 250 | } 251 | } 252 | 253 | private void DoInsideProc(char chr) 254 | { 255 | 256 | if ((chr >= 'A' && chr <= 'Z') || (chr >= 'a' && chr <= 'z') || (chr == '_') || (chr == '#')) { IdentProc(); return; } 257 | if (chr >= '0' && chr <= '9') { NumberProc(); return; } 258 | if ((chr >= '\x00' && chr <= '\x09') || (chr >= '\x0B' && chr <= '\x0C') || (chr >= '\x0E' && chr <= '\x20')) { SpaceProc(); return; } 259 | UnknownProc(); 260 | } 261 | 262 | private void SpaceProc() 263 | { 264 | m_TokenId = TokenKind.tkSpace; 265 | char c; 266 | do { m_Run++; c = GetChar(m_Run); } 267 | while (!(c > '\x20' || c == '\x00' || c == '\x0A' || c == '\x0D')); 268 | } 269 | 270 | private void UnknownProc() 271 | { 272 | m_Run++; 273 | m_TokenId = TokenKind.tkUnknown; 274 | } 275 | 276 | private void NumberProc() 277 | { 278 | m_TokenId = TokenKind.tkNumber; 279 | if (GetChar(m_Run) == '0' && (GetChar(m_Run + 1) == 'X' || GetChar(m_Run + 1) == 'x')) 280 | { 281 | m_Run += 2; 282 | while (HexDigits.IndexOf(GetChar(m_Run)) != -1) m_Run++; 283 | return; 284 | } 285 | m_Run++; 286 | m_TokenId = TokenKind.tkNumber; 287 | while (NumberStr.IndexOf(GetChar(m_Run)) != -1) 288 | { 289 | if (GetChar(m_Run) == '.' && GetChar(m_Run + 1) == '.') break; 290 | m_Run++; 291 | } 292 | 293 | } 294 | 295 | private void QuoteProc() 296 | { 297 | m_TokenId = TokenKind.tkIdentifier; 298 | m_Run++; 299 | while (!(GetChar(m_Run) == '\x00' || GetChar(m_Run) == '\x0A' || GetChar(m_Run) == '\x0D')) 300 | { 301 | if (GetChar(m_Run) == '\x22') { m_Run++; break; } 302 | m_Run++; 303 | } 304 | } 305 | 306 | private void BracketProc() 307 | { 308 | 309 | m_TokenId = TokenKind.tkIdentifier; 310 | m_Run++; 311 | while (!(GetChar(m_Run) == '\x00' || GetChar(m_Run) == '\x0A' || GetChar(m_Run) == '\x0D')) 312 | { 313 | if (GetChar(m_Run) == ']') { m_Run++; break; } 314 | m_Run++; 315 | } 316 | 317 | } 318 | 319 | private void SymbolProc() 320 | { 321 | m_Run++; 322 | m_TokenId = TokenKind.tkSymbol; 323 | } 324 | 325 | private void SymbolAssignProc() 326 | { 327 | m_TokenId = TokenKind.tkSymbol; 328 | m_Run++; 329 | if (GetChar(m_Run) == '=') m_Run++; 330 | } 331 | 332 | private void KeyHash(int pos) 333 | { 334 | m_StringLen = 0; 335 | while (System.Array.BinarySearch(m_IdentifiersArray, GetChar(pos)) >= 0) { m_StringLen++; pos++; } 336 | return; 337 | } 338 | private TokenKind IdentKind() 339 | { 340 | KeyHash(m_Run); 341 | return m_Tokens[m_Line.Substring(m_TokenPos, m_Run + m_StringLen - m_TokenPos)]; 342 | } 343 | private void IdentProc() 344 | { 345 | m_TokenId = IdentKind(); 346 | m_Run += m_StringLen; 347 | if (m_TokenId == TokenKind.tkComment) 348 | { 349 | while (!(GetChar(m_Run) == '\x00' || GetChar(m_Run) == '\x0A' || GetChar(m_Run) == '\x0D')) { m_Run++; } 350 | } 351 | else 352 | { 353 | while (IdentifierStr.IndexOf(GetChar(m_Run)) != -1) m_Run++; 354 | } 355 | } 356 | private void VariableProc() 357 | { 358 | if (GetChar(m_Run) == '@' && GetChar(m_Run + 1) == '@') { m_Run += 2; IdentProc(); } 359 | else 360 | { 361 | m_TokenId = TokenKind.tkVariable; 362 | int i = m_Run; 363 | do { i++; } while (!(IdentifierStr.IndexOf(GetChar(i)) == -1)); 364 | m_Run = i; 365 | } 366 | } 367 | 368 | private void AndSymbolProc() 369 | { 370 | m_TokenId = TokenKind.tkSymbol; 371 | m_Run++; 372 | if (GetChar(m_Run) == '=' || GetChar(m_Run) == '&') m_Run++; 373 | } 374 | 375 | private void SlashProc() 376 | { 377 | m_Run++; 378 | switch (GetChar(m_Run)) 379 | { 380 | case '*': 381 | { 382 | Range = SqlRange.rsComment; 383 | m_TokenId = TokenKind.tkComment; 384 | do 385 | { 386 | m_Run++; 387 | if (GetChar(m_Run) == '*' && GetChar(m_Run + 1) == '/') { Range = SqlRange.rsUnknown; m_Run += 2; break; } 388 | } while (!(GetChar(m_Run) == '\x00' || GetChar(m_Run) == '\x0D' || GetChar(m_Run) == '\x0A')); 389 | } 390 | break; 391 | case '=': m_Run++; m_TokenId = TokenKind.tkSymbol; break; 392 | default: m_TokenId = TokenKind.tkSymbol; break; 393 | 394 | } 395 | } 396 | 397 | private void PlusProc() 398 | { 399 | m_TokenId = TokenKind.tkSymbol; 400 | m_Run++; 401 | if (GetChar(m_Run) == '=' || GetChar(m_Run) == '=') m_Run++; 402 | 403 | } 404 | 405 | private void OrSymbolProc() 406 | { 407 | m_TokenId = TokenKind.tkSymbol; 408 | m_Run++; 409 | if (GetChar(m_Run) == '=' || GetChar(m_Run) == '|') m_Run++; 410 | } 411 | 412 | private void MinusProc() 413 | { 414 | m_Run++; 415 | if (GetChar(m_Run) == '-') 416 | { 417 | m_TokenId = TokenKind.tkComment; 418 | char c; 419 | do 420 | { 421 | m_Run++; 422 | c = GetChar(m_Run); 423 | } while (!(c == '\x00' || c == '\x0A' || c == '\x0D')); 424 | } 425 | else { m_TokenId = TokenKind.tkSymbol; } 426 | } 427 | 428 | private void LowerProc() 429 | { 430 | m_TokenId = TokenKind.tkSymbol; 431 | m_Run++; 432 | switch (GetChar(m_Run)) 433 | { 434 | case '=': m_Run++; break; 435 | case '<': m_Run++; if (GetChar(m_Run) == '=') m_Run++; break; 436 | } 437 | 438 | } 439 | 440 | private void GreaterProc() 441 | { 442 | m_TokenId = TokenKind.tkSymbol; 443 | m_Run++; 444 | if (GetChar(m_Run) == '=' || GetChar(m_Run) == '>') m_Run++; 445 | } 446 | 447 | private void EqualProc() 448 | { 449 | m_TokenId = TokenKind.tkSymbol; 450 | m_Run++; 451 | if (GetChar(m_Run) == '=' || GetChar(m_Run) == '>') m_Run++; 452 | } 453 | 454 | private void Next() 455 | { 456 | m_TokenPos = m_Run; 457 | switch (Range) 458 | { 459 | case SqlRange.rsComment: AnsiCProc(); break; 460 | case SqlRange.rsString: AsciiCharProc(); break; 461 | default: DoProcTable(GetChar(m_Run)); break; 462 | } 463 | m_Token = m_Line.Substring(m_TokenPos, m_Run - m_TokenPos); 464 | } 465 | 466 | 467 | } 468 | 469 | 470 | } 471 | -------------------------------------------------------------------------------- /sql_profiler/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace sql_profiler 3 | { 4 | 5 | 6 | public class Program 7 | { 8 | 9 | // https://docs.microsoft.com/en-us/sql/relational-databases/sql-trace/create-and-run-traces-using-transact-sql-stored-procedures 10 | // https://docs.microsoft.com/en-us/sql/relational-databases/sql-trace/create-a-trace-transact-sql 11 | // https://docs.microsoft.com/en-us/sql/relational-databases/sql-trace/set-a-trace-filter-transact-sql 12 | // https://docs.microsoft.com/en-us/sql/relational-databases/sql-trace/modify-an-existing-trace-transact-sql 13 | // https://docs.microsoft.com/en-us/sql/relational-databases/sql-trace/view-a-saved-trace-transact-sql 14 | // https://docs.microsoft.com/en-us/sql/relational-databases/sql-trace/delete-a-trace-transact-sql 15 | 16 | // Create a trace by using sp_trace_create. 17 | // Add events with sp_trace_setevent. 18 | // (Optional) Set a filter with sp_trace_setfilter. 19 | // Start the trace with sp_trace_setstatus. 20 | // Stop the trace with sp_trace_setstatus. 21 | // Close the trace with sp_trace_setstatus. 22 | 23 | // https://stackoverflow.com/questions/637013/how-do-i-find-running-traces-in-sql-server 24 | // SELECT * FROM sys.traces 25 | // SELECT * FROM::fn_trace_getinfo(trace_id) 26 | // SELECT * FROM::fn_trace_getfilterinfo(trace_id) 27 | 28 | // A trace must be stopped first before it can be closed. 29 | // EXEC sp_trace_setstatus [ @traceid = ] trace_id , [ @status = ] status 30 | 31 | // EXEC sp_trace_setstatus 2, 0 32 | // EXEC sp_trace_setstatus 2, 2 33 | 34 | // Execute sp_trace_setstatus by specifying @status = 0 to stop the trace. 35 | // Execute sp_trace_setstatus by specifying @status = 2 to close the trace and delete its information from the server. 36 | 37 | private static ExpressProfiler.SqlServerProfiler s_profiler; 38 | 39 | 40 | public class Argument 41 | { 42 | public string Key; 43 | 44 | private object m_value; 45 | private object InternalValue 46 | { 47 | get 48 | { 49 | if (this.m_value != null) 50 | return this.m_value; 51 | 52 | if (!CommandLine.ContainsKey(this.Key)) 53 | return null; 54 | 55 | if (object.ReferenceEquals(@Type, typeof(string))) 56 | { 57 | this.m_value = CommandLine.GetValue(this.Key); 58 | return this.m_value; 59 | } // End if (object.ReferenceEquals(@Type, typeof(string))) 60 | 61 | if (object.ReferenceEquals(@Type, typeof(bool))) 62 | { 63 | bool? arg = CommandLine.GetValue(this.Key); 64 | if (!arg.HasValue) 65 | arg = false; 66 | 67 | this.m_value = arg.Value; 68 | return this.m_value; 69 | } // End if (object.ReferenceEquals(@Type, typeof(bool))) 70 | 71 | if (object.ReferenceEquals(@Type, typeof(int))) 72 | { 73 | int? arg = CommandLine.GetValue(this.Key); 74 | if (!arg.HasValue) 75 | arg = 0; 76 | 77 | this.m_value = arg.Value; 78 | return this.m_value; 79 | } // End if (object.ReferenceEquals(@Type, typeof(int))) 80 | 81 | if (object.ReferenceEquals(@Type, typeof(long))) 82 | { 83 | long? arg = CommandLine.GetValue(this.Key); 84 | if (!arg.HasValue) 85 | arg = 0; 86 | 87 | this.m_value = arg.Value; 88 | return this.m_value; 89 | } // End if (object.ReferenceEquals(@Type, typeof(long))) 90 | 91 | return this.m_value; 92 | } // End Get 93 | 94 | } // End Property InternalValue 95 | 96 | 97 | public T Value() 98 | { 99 | return (T) this.InternalValue; 100 | } // End Function Value 101 | 102 | 103 | public string StringValue 104 | { 105 | get { return this.CommandLine[this.Key]; } 106 | } // End Property StringValue 107 | 108 | 109 | public bool IsPresent 110 | { 111 | get { return this.CommandLine.ContainsKey(this.Key); } 112 | } // End Property IsPresent 113 | 114 | 115 | public System.Type @Type; 116 | public string HelpText; 117 | public bool Required; 118 | public bool IsCommand; 119 | 120 | public sql_profiler.CommandLineArguments CommandLine; 121 | } // End Class Argument 122 | 123 | 124 | public static System.Collections.Generic.Dictionary 125 | GetCommandLineArguments(string[] args 126 | , System.Collections.Generic.Dictionary defaultValues) 127 | { 128 | sql_profiler.CommandLineArguments arguments = 129 | new sql_profiler.CommandLineArguments(args, defaultValues); 130 | 131 | 132 | System.Collections.Generic.Dictionary ls = new 133 | System.Collections.Generic.Dictionary( 134 | System.StringComparer.InvariantCultureIgnoreCase 135 | ); 136 | 137 | ls.Add("server", 138 | new Argument() 139 | { 140 | Key = "server" 141 | , @Type=typeof(string) 142 | , HelpText = @"The server\instance on which the DB to profile is" 143 | , Required = true 144 | } 145 | ); 146 | 147 | ls.Add("db", 148 | new Argument() 149 | { 150 | Key = "db" 151 | , @Type=typeof(string) 152 | , HelpText = "The db to profile" 153 | , Required = true 154 | } 155 | ); 156 | 157 | ls.Add("username", 158 | new Argument() 159 | { 160 | Key = "username" 161 | , @Type=typeof(string) 162 | , HelpText = "The SQL user-name; On Windows, uses integrated security if username is NULL or EMPTY." 163 | , Required = false 164 | } 165 | ); 166 | 167 | ls.Add("password", 168 | new Argument() 169 | { 170 | Key = "password" 171 | , @Type=typeof(string) 172 | , HelpText = "The password for the sql-user" 173 | , Required = false 174 | } 175 | ); 176 | 177 | 178 | ls.Add("help", 179 | new Argument() 180 | { 181 | Key = "help" 182 | , @Type=typeof(string) 183 | , HelpText = "Display help" 184 | , Required = false 185 | , IsCommand = true 186 | } 187 | ); 188 | 189 | 190 | ls.Add("list", 191 | new Argument() 192 | { 193 | Key = "list" 194 | , @Type=typeof(string) 195 | , HelpText = "Show the command line values used." 196 | , Required = false 197 | , IsCommand = true 198 | } 199 | ); 200 | 201 | 202 | ls.Add("showinput", 203 | new Argument() 204 | { 205 | Key = "showinput" 206 | , @Type=typeof(string) 207 | , HelpText = "Show the command line values as passed from console." 208 | , Required = false 209 | , IsCommand = true 210 | } 211 | ); 212 | 213 | if (arguments != null) 214 | { 215 | foreach (System.Collections.Generic.KeyValuePair kvp in ls) 216 | { 217 | kvp.Value.CommandLine = arguments; 218 | } // Next kvp 219 | 220 | } // End if (arguments != null) 221 | 222 | return ls; 223 | } // End Function GetCommandLineArguments 224 | 225 | public static void Help(System.Collections.Generic.Dictionary arg_list) 226 | { 227 | System.Console.WriteLine("Valid command-line arguments:"); 228 | 229 | foreach(System.Collections.Generic.KeyValuePair kvp in arg_list) 230 | { 231 | System.Console.WriteLine($" --{kvp.Key}: {kvp.Value.HelpText}"); 232 | } // Next kvp 233 | 234 | } // End Sub Help 235 | 236 | 237 | public static void ListValues(System.Collections.Generic.Dictionary arg_list) 238 | { 239 | System.Console.WriteLine("Used command-line argument's values:"); 240 | 241 | foreach (System.Collections.Generic.KeyValuePair kvp in arg_list) 242 | { 243 | if (!kvp.Value.IsCommand) 244 | System.Console.WriteLine($"{kvp.Key}: {kvp.Value.StringValue}"); 245 | } // Next kvp 246 | 247 | } // End Sub ListValues 248 | 249 | 250 | public static void ShowInput(string[] args) 251 | { 252 | 253 | for (int i = 0; i < args.Length; ++i) 254 | { 255 | System.Console.WriteLine($"{i}: {args[i]}"); 256 | } // Next i 257 | 258 | } // End Sub ShowInput 259 | 260 | 261 | public static string GetPlatformDefaultInstance() 262 | { 263 | bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform( 264 | System.Runtime.InteropServices.OSPlatform.Windows 265 | ); 266 | 267 | // TODO: Check if there is an instance SQLExpress 268 | // https://stackoverflow.com/questions/141154/how-can-i-determine-installed-sql-server-instances-and-their-versions 269 | // Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSRS13.SQLEXPRESS 270 | // Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL13.SQLEXPRESS 271 | // Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL13E.LOCALDB 272 | // Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQLServer 273 | 274 | if (isWindows) 275 | return System.Environment.MachineName + @"\" + "SQLEXPRESS"; 276 | 277 | return System.Environment.MachineName; 278 | } // End Function GetPlatformDefaultInstance 279 | 280 | 281 | static void Main(string[] args) 282 | { 283 | System.Console.Clear(); 284 | System.Console.Title = "https://github.com/ststeiger/sql_profiler"; 285 | 286 | ᅠ300 = new System.Timers.Timer(4000); 287 | ᅠ300.AutoReset = true; 288 | ᅠ300.Elapsed += new System.Timers.ElapsedEventHandler(Sparta_Elapsed); 289 | ᅠ300.Start(); 290 | 291 | MainTest(args); 292 | // DoProfiling(args); 293 | } 294 | 295 | // https://stackoverflow.com/a/48274520 296 | private static System.Timers.Timer ᅠ300; 297 | private static bool s_showSparta = true; 298 | 299 | private static void Sparta_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 300 | { 301 | if(s_showSparta) 302 | System.Console.Title = "THIS IS MADNESS!!! Madness huh? THIS IS SPARTA!!!!!!! "; 303 | else 304 | System.Console.Title = "https://github.com/ststeiger/sql_profiler"; 305 | 306 | s_showSparta ^= true; 307 | } 308 | 309 | 310 | static void MainTest(string[] args) 311 | { 312 | string instance = GetPlatformDefaultInstance(); 313 | // dotnet run --server localhost --username MY_USER --password MY_PASSWORD --db MY_DB 314 | // string ar = $"--server {instance} --username WebAppWebServices --password TOP_SECRET --Db COR_Basic_Demo_V4"; 315 | 316 | string ar = $"--server {instance} /db \"COR_Basic_Demo_V4\""; 317 | 318 | bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform( 319 | System.Runtime.InteropServices.OSPlatform.Windows 320 | ); 321 | 322 | if(!isWindows) 323 | { 324 | try 325 | { 326 | string un = TestPlotly.SecretManager.GetSecret("DefaultDbUser"); 327 | string pw = TestPlotly.SecretManager.GetSecret("DefaultDbPassword"); 328 | ar = $"--server {instance} --username {un} --password {pw} --db \"Redmine\""; 329 | } 330 | catch (System.Exception e) 331 | { 332 | System.Console.WriteLine(e); 333 | throw; 334 | } 335 | } 336 | 337 | DoProfiling(ar.Split(' ')); 338 | } // End Sub Main 339 | 340 | 341 | static void DoProfiling(string[] args) 342 | { 343 | // https://github.com/dotnet/coreclr/issues/8565 344 | // https://shazwazza.com/post/aspnet-core-application-shutdown-events/ 345 | // Will not be executed when !windows 346 | WindowsFix.AddConsoleHandler(ConsoleCtrlCheck); 347 | 348 | System.AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 349 | System.AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; 350 | System.Console.CancelKeyPress += Console_CancelKeyPress; 351 | 352 | System.Collections.Generic.Dictionary defaultValues = 353 | new System.Collections.Generic.Dictionary(); 354 | 355 | defaultValues["server"] = GetPlatformDefaultInstance(); 356 | defaultValues["db"] = "COR_Basic_Demo_V4"; 357 | 358 | System.Collections.Generic.Dictionary arg_list = 359 | GetCommandLineArguments(args, defaultValues); 360 | 361 | 362 | if (arg_list["showinput"].IsPresent) 363 | { 364 | ShowInput(args); 365 | System.Console.WriteLine(System.Environment.NewLine); 366 | System.Console.WriteLine("--- Press any key to stop continue --- "); 367 | System.Console.ReadKey(); 368 | return; 369 | } 370 | 371 | if (arg_list["list"].IsPresent) 372 | { 373 | ListValues(arg_list); 374 | System.Console.WriteLine(System.Environment.NewLine); 375 | System.Console.WriteLine("--- Press any key to stop continue --- "); 376 | System.Console.ReadKey(); 377 | return; 378 | } 379 | 380 | if (arg_list["help"].IsPresent) 381 | { 382 | Help(arg_list); 383 | System.Console.WriteLine(System.Environment.NewLine); 384 | System.Console.WriteLine("--- Press any key to stop continue --- "); 385 | System.Console.ReadKey(); 386 | return; 387 | } 388 | 389 | 390 | string server = arg_list["server"].Value(); 391 | string db = arg_list["db"].Value(); 392 | string username = arg_list["username"].Value(); 393 | string password = arg_list["password"].Value(); 394 | 395 | 396 | s_profiler = new ExpressProfiler.SqlServerProfiler(server, db, username, password); 397 | 398 | s_profiler.StartProfiling(); 399 | 400 | 401 | System.Console.ResetColor(); 402 | 403 | // System.Console.WriteLine("--- Press ENTER to stop profiling --- "); 404 | // System.Console.ReadLine(); 405 | 406 | // System.Console.WriteLine("--- Press any key to stop profiling --- "); 407 | // System.Console.ReadKey(); 408 | 409 | System.Console.WriteLine("--- Press ENTER to stop profiling --- "); 410 | 411 | System.ConsoleKey cc = default(System.ConsoleKey); 412 | 413 | do 414 | { 415 | // THIS IS MADNESS!!! Madness huh? THIS IS SPARTA!!!!!!! 416 | while (!System.Console.KeyAvailable) 417 | { 418 | System.Threading.Thread.Sleep(100); 419 | } 420 | 421 | cc = System.Console.ReadKey().Key; 422 | 423 | if(cc == System.ConsoleKey.C) 424 | System.Console.Clear(); 425 | 426 | } while (cc != System.ConsoleKey.Enter); 427 | 428 | OnExit(); 429 | } // End Sub Test 430 | 431 | 432 | [System.Runtime.CompilerServices.MethodImpl( 433 | System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining) 434 | ] 435 | private static void OnExit() 436 | { 437 | System.Console.ResetColor(); 438 | 439 | if (s_profiler != null) // Is there any chance this could happen ? 440 | s_profiler.StopProfiling(); 441 | 442 | System.Console.ResetColor(); 443 | } // End Sub OnExit 444 | 445 | 446 | private static bool ConsoleCtrlCheck(WindowsFix.CtrlTypes ctrlType) 447 | { 448 | // Put your own handler here 449 | switch (ctrlType) 450 | { 451 | case WindowsFix.CtrlTypes.CTRL_C_EVENT: // CTRL+C received! 452 | case WindowsFix.CtrlTypes.CTRL_BREAK_EVENT: // CTRL+BREAK received! 453 | case WindowsFix.CtrlTypes.CTRL_CLOSE_EVENT: // Program being closed! 454 | case WindowsFix.CtrlTypes.CTRL_LOGOFF_EVENT: // User is logging off! 455 | case WindowsFix.CtrlTypes.CTRL_SHUTDOWN_EVENT: 456 | OnExit(); 457 | break; 458 | } // End switch (ctrlType) 459 | 460 | return true; 461 | } // End Function ConsoleCtrlCheck 462 | 463 | 464 | // Catch CTRL+C 465 | private static void Console_CancelKeyPress(object sender, System.ConsoleCancelEventArgs e) 466 | { 467 | OnExit(); 468 | } // End Sub Console_CancelKeyPress 469 | 470 | 471 | // Does not catch anything... 472 | private static void CurrentDomain_ProcessExit(object sender, System.EventArgs e) 473 | { 474 | OnExit(); 475 | } // End Sub CurrentDomain_ProcessExit 476 | 477 | 478 | // Catch unhandled exceptions 479 | private static void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e) 480 | { 481 | System.Console.WriteLine(((System.Exception)e.ExceptionObject).Message, "Error"); 482 | OnExit(); 483 | } // End Sub CurrentDomain_UnhandledException 484 | 485 | 486 | } // End Class Program 487 | 488 | 489 | } // End Namespace sql_profiler 490 | -------------------------------------------------------------------------------- /sql_profiler/Code/SqlServerProfiler.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | 4 | namespace ExpressProfiler 5 | { 6 | 7 | 8 | public class SqlServerProfiler 9 | { 10 | protected enum ProfilingStateEnum { psStopped, psProfiling, psPaused } 11 | protected ProfilingStateEnum m_ProfilingState; 12 | 13 | protected System.Data.SqlClient.SqlConnection m_Conn; 14 | protected RawTraceReader m_Rdr; 15 | protected bool m_NeedStop; 16 | protected System.Timers.Timer m_timer; 17 | protected System.Threading.Thread m_Thr; 18 | protected System.Collections.Concurrent.ConcurrentQueue m_events; 19 | protected readonly System.Collections.Generic.List m_columns; 20 | protected readonly YukonLexer m_Lex; 21 | protected readonly bool m_isWindows; 22 | 23 | 24 | protected readonly ProfilerEvent m_EventStarted = new ProfilerEvent(); 25 | protected readonly ProfilerEvent m_EventStopped = new ProfilerEvent(); 26 | protected readonly ProfilerEvent m_EventPaused = new ProfilerEvent(); 27 | 28 | 29 | protected string m_server; 30 | protected string m_username; 31 | protected string m_password; 32 | protected bool m_integrated_security; 33 | protected string m_database; 34 | 35 | 36 | public SqlServerProfiler() 37 | :this(System.Environment.MachineName + @"\" + "SQLEXPRESS") 38 | { } 39 | 40 | public SqlServerProfiler(string server) 41 | : this(server, null) 42 | { } 43 | 44 | public SqlServerProfiler(string server, string database) 45 | : this(server, database, null, null) 46 | { } 47 | 48 | 49 | public SqlServerProfiler(string server, string database 50 | , string username, string password) 51 | { 52 | this.m_server = server; 53 | this.m_database = database; 54 | this.m_username = username; 55 | this.m_password = password; 56 | this.m_integrated_security = string.IsNullOrWhiteSpace(username); 57 | 58 | this.m_isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform( 59 | System.Runtime.InteropServices.OSPlatform.Windows 60 | ); 61 | 62 | if (this.m_integrated_security && !this.m_isWindows) 63 | { 64 | throw new System.ArgumentException($"Username is NULL or empty. Cannot use integrated-security on non-windows platform."); 65 | } 66 | 67 | if (!this.m_integrated_security) 68 | { 69 | if (password == null) 70 | throw new System.ArgumentException($"{nameof(password)} cannot be NULL when integrated security is false."); 71 | } // End if (!integratedSecurity) 72 | 73 | 74 | this.m_Lex = new YukonLexer(); 75 | //this.m_events = new Queue(10); 76 | this.m_events = new System.Collections.Concurrent.ConcurrentQueue(); 77 | this.m_timer = new System.Timers.Timer(1000); 78 | this.m_timer.AutoReset = false; 79 | this.m_timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed); 80 | this.m_timer.Start(); 81 | 82 | this.m_columns = new System.Collections.Generic.List(); 83 | this.m_columns.Add(new PerfColumn { Caption = "Event Class", Column = ProfilerEventColumns.EventClass, Width = 122 }); 84 | this.m_columns.Add(new PerfColumn { Caption = "Text Data", Column = ProfilerEventColumns.TextData, Width = 255 }); 85 | this.m_columns.Add(new PerfColumn { Caption = "Login Name", Column = ProfilerEventColumns.LoginName, Width = 79 }); 86 | this.m_columns.Add(new PerfColumn { Caption = "CPU", Column = ProfilerEventColumns.CPU, Width = 82, Alignment = HorizontalAlignment.Right, Format = "#,0" }); 87 | this.m_columns.Add(new PerfColumn { Caption = "Reads", Column = ProfilerEventColumns.Reads, Width = 78, Alignment = HorizontalAlignment.Right, Format = "#,0" }); 88 | this.m_columns.Add(new PerfColumn { Caption = "Writes", Column = ProfilerEventColumns.Writes, Width = 78, Alignment = HorizontalAlignment.Right, Format = "#,0" }); 89 | this.m_columns.Add(new PerfColumn { Caption = "Duration, ms", Column = ProfilerEventColumns.Duration, Width = 82, Alignment = HorizontalAlignment.Right, Format = "#,0" }); 90 | this.m_columns.Add(new PerfColumn { Caption = "SPID", Column = ProfilerEventColumns.SPID, Width = 50, Alignment = HorizontalAlignment.Right }); 91 | 92 | // if (m_currentsettings.EventsColumns.StartTime) 93 | m_columns.Add(new PerfColumn { Caption = "Start time", Column = ProfilerEventColumns.StartTime, Width = 140, Format = "yyyy-MM-ddThh:mm:ss.ffff" }); 94 | // if (m_currentsettings.EventsColumns.EndTime) 95 | m_columns.Add(new PerfColumn { Caption = "End time", Column = ProfilerEventColumns.EndTime, Width = 140, Format = "yyyy-MM-ddThh:mm:ss.ffff" }); 96 | // if (m_currentsettings.EventsColumns.DatabaseName) 97 | m_columns.Add(new PerfColumn { Caption = "DatabaseName", Column = ProfilerEventColumns.DatabaseName, Width = 70 }); 98 | // if (m_currentsettings.EventsColumns.ObjectName) 99 | m_columns.Add(new PerfColumn { Caption = "Object name", Column = ProfilerEventColumns.ObjectName, Width = 70 }); 100 | // if (m_currentsettings.EventsColumns.ApplicationName) 101 | m_columns.Add(new PerfColumn { Caption = "Application name", Column = ProfilerEventColumns.ApplicationName, Width = 70 }); 102 | // if (m_currentsettings.EventsColumns.HostName) 103 | m_columns.Add(new PerfColumn { Caption = "Host name", Column = ProfilerEventColumns.HostName, Width = 70 }); 104 | 105 | // m_columns.Add(new PerfColumn { Caption = "#", Column = -1, Width = 53, Alignment = HorizontalAlignment.Right }); 106 | } // End Constructor 107 | 108 | 109 | 110 | protected void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 111 | { 112 | this.m_timer.Stop(); 113 | 114 | try 115 | { 116 | int i = -1; 117 | while ((i = this.m_events.Count) > 0) 118 | { 119 | ProfilerEvent evt; 120 | if (this.m_events.TryDequeue(out evt)) 121 | NewEventArrived(evt, i == 1); 122 | else 123 | System.Threading.Thread.Sleep(50); 124 | } // Whend 125 | 126 | } // End try 127 | catch (System.Exception ex) 128 | { 129 | System.Console.WriteLine($"Timer_Elapsed Error: {ex.Message}\n{ex.StackTrace}"); 130 | } 131 | 132 | this.m_timer.Start(); 133 | } // End Sub Timer_Elapsed 134 | 135 | 136 | protected System.Data.SqlClient.SqlConnection GetConnection() 137 | { 138 | string cs = string.Format(@"Data Source = {0}; Initial Catalog = master; 139 | Integrated Security=SSPI;Application Name=Express Profiler", this.m_server); 140 | 141 | if (!this.m_integrated_security) 142 | { 143 | cs = string.Format(@"Data Source={0};Initial Catalog=master; 144 | User Id={1};Password='{2}';;Application Name=Express Profiler" 145 | , this.m_server, this.m_username, this.m_password); 146 | } // End if (!this.m_integrated_security) 147 | 148 | return new System.Data.SqlClient.SqlConnection(cs); 149 | } // End Function GetConnection 150 | 151 | 152 | protected void OpenConnection(System.Data.SqlClient.SqlConnection con) 153 | { 154 | if (con.State != System.Data.ConnectionState.Open) 155 | con.Open(); 156 | } // End Sub OpenConnection 157 | 158 | protected void CloseConnection(System.Data.SqlClient.SqlConnection con) 159 | { 160 | if (con.State != System.Data.ConnectionState.Closed) 161 | con.Close(); 162 | } // End Sub CloseConnection 163 | 164 | 165 | protected void ProfilerThread(object state) 166 | { 167 | try 168 | { 169 | while (!this.m_NeedStop && this.m_Rdr.TraceIsActive) 170 | { 171 | ProfilerEvent evt = this.m_Rdr.Next(); 172 | if (evt != null) 173 | { 174 | // lock (this) 175 | m_events.Enqueue(evt); 176 | } // End if (evt != null) 177 | } // Whend 178 | } 179 | catch (System.Exception e) 180 | { 181 | // lock (this) 182 | // { 183 | if (!this.m_NeedStop && this.m_Rdr.TraceIsActive) 184 | { 185 | System.Console.WriteLine($"Error: {e.Message}\n{e.StackTrace}"); 186 | } 187 | // } // End lock 188 | } // End Catch 189 | } // End Sub ProfilerThread 190 | 191 | 192 | /* 193 | protected void RunProfiling(bool showfilters) 194 | { 195 | if (showfilters) 196 | { 197 | // ts m_currentsettings.GetCopy(); 198 | TraceProperties.TraceSettings ts = new TraceProperties.TraceSettings(); 199 | using (TraceProperties frm = new TraceProperties()) 200 | { 201 | frm.SetSettings(ts); 202 | // if (DialogResult.OK != frm.ShowDialog()) return; 203 | // m_currentsettings = frm.m_currentsettings.GetCopy(); 204 | } 205 | } 206 | 207 | StartProfiling(); 208 | } // End Sub RunProfiling 209 | */ 210 | 211 | public enum StringFilterCondition 212 | { 213 | Like, 214 | NotLike 215 | } // End Enum StringFilterCondition 216 | 217 | public enum IntFilterCondition 218 | { 219 | Equal, 220 | NotEqual, 221 | GreaterThan, 222 | LessThan 223 | } // End Enum IntFilterCondition 224 | 225 | 226 | protected void SetIntFilter(int? value, IntFilterCondition condition, int column) 227 | { 228 | int[] com = new[] { 229 | ComparisonOperators.Equal 230 | , ComparisonOperators.NotEqual 231 | , ComparisonOperators.GreaterThan 232 | , ComparisonOperators.LessThan 233 | }; 234 | 235 | if ((null != value)) 236 | { 237 | long? v = value; 238 | this.m_Rdr.SetFilter(column, LogicalOperators.AND, com[(int)condition], v); 239 | } // End if ((null != value)) 240 | 241 | } // End Sub SetIntFilter 242 | 243 | 244 | protected void SetStringFilter(string value, StringFilterCondition condition, int column) 245 | { 246 | if (!string.IsNullOrEmpty(value)) 247 | { 248 | this.m_Rdr.SetFilter(column, LogicalOperators.AND 249 | , condition == StringFilterCondition.Like ? 250 | ComparisonOperators.Like : ComparisonOperators.NotLike 251 | , value 252 | ); 253 | } // End if (!string.IsNullOrEmpty(value)) 254 | 255 | } // End Sub SetStringFilter 256 | 257 | 258 | public void StartProfiling() 259 | { 260 | this.m_events.Clear(); 261 | 262 | this.m_Conn = GetConnection(); 263 | OpenConnection(this.m_Conn); 264 | 265 | this.m_Rdr = new RawTraceReader(m_Conn); 266 | this.m_Rdr.CreateTrace(); 267 | 268 | //if (m_currentsettings.EventsColumns.BatchCompleted) 269 | { 270 | m_Rdr.SetEvent(ProfilerEvents.TSQL.SQLBatchCompleted, 271 | ProfilerEventColumns.TextData, 272 | ProfilerEventColumns.LoginName, 273 | ProfilerEventColumns.CPU, 274 | ProfilerEventColumns.Reads, 275 | ProfilerEventColumns.Writes, 276 | ProfilerEventColumns.Duration, 277 | ProfilerEventColumns.SPID, 278 | ProfilerEventColumns.StartTime, 279 | ProfilerEventColumns.EndTime, 280 | ProfilerEventColumns.DatabaseName, 281 | ProfilerEventColumns.ApplicationName, 282 | ProfilerEventColumns.HostName 283 | ); 284 | } // End if (m_currentsettings.EventsColumns.BatchCompleted) 285 | 286 | //if (m_currentsettings.EventsColumns.RPCCompleted) 287 | { 288 | m_Rdr.SetEvent(ProfilerEvents.StoredProcedures.RPCCompleted, 289 | ProfilerEventColumns.TextData, ProfilerEventColumns.LoginName, 290 | ProfilerEventColumns.CPU, ProfilerEventColumns.Reads, 291 | ProfilerEventColumns.Writes, ProfilerEventColumns.Duration, 292 | ProfilerEventColumns.SPID 293 | , ProfilerEventColumns.StartTime, ProfilerEventColumns.EndTime 294 | , ProfilerEventColumns.DatabaseName 295 | , ProfilerEventColumns.ObjectName 296 | , ProfilerEventColumns.ApplicationName 297 | , ProfilerEventColumns.HostName 298 | 299 | ); 300 | } // End if (m_currentsettings.EventsColumns.RPCCompleted) 301 | 302 | 303 | if (!string.IsNullOrWhiteSpace(this.m_database)) 304 | SetStringFilter(this.m_database, StringFilterCondition.Like, ProfilerEventColumns.DatabaseName); 305 | 306 | this.m_Rdr.SetFilter(ProfilerEventColumns.ApplicationName, LogicalOperators.AND 307 | , ComparisonOperators.NotLike, "Express Profiler"); 308 | 309 | 310 | this.m_Rdr.StartTrace(); 311 | this.m_NeedStop = false; 312 | this.m_Thr = new System.Threading.Thread(ProfilerThread) { 313 | IsBackground = true, 314 | Priority = System.Threading.ThreadPriority.Lowest 315 | }; 316 | 317 | this.m_ProfilingState = ProfilingStateEnum.psProfiling; 318 | NewEventArrived(m_EventStarted, true); 319 | m_Thr.Start(); 320 | } // End Sub StartProfiling 321 | 322 | 323 | 324 | public void PauseProfiling() 325 | { 326 | if (this.m_ProfilingState != ProfilingStateEnum.psProfiling) 327 | return; 328 | 329 | using (System.Data.SqlClient.SqlConnection cn = GetConnection()) 330 | { 331 | OpenConnection(cn); 332 | this.m_Rdr.StopTrace(cn); 333 | CloseConnection(cn); 334 | } // End Using cn 335 | 336 | this.m_ProfilingState = ProfilingStateEnum.psPaused; 337 | NewEventArrived(m_EventPaused, true); 338 | } // End Sub PauseProfiling 339 | 340 | 341 | public void StopProfiling() 342 | { 343 | if (this.m_ProfilingState == ProfilingStateEnum.psStopped) 344 | return; 345 | 346 | using (System.Data.SqlClient.SqlConnection cn = GetConnection()) 347 | { 348 | OpenConnection(cn); 349 | this.m_Rdr.StopTrace(cn); 350 | this.m_Rdr.CloseTrace(cn); 351 | CloseConnection(cn); 352 | } // End Using cn 353 | 354 | this.m_NeedStop = true; 355 | this.m_ProfilingState = ProfilingStateEnum.psStopped; 356 | NewEventArrived(m_EventStopped, true); 357 | } // End Sub StopProfiling 358 | 359 | 360 | protected string GetEventCaption(ProfilerEvent evt) 361 | { 362 | if (evt == m_EventStarted) 363 | return "Trace started"; 364 | 365 | if (evt == m_EventPaused) 366 | return "Trace paused"; 367 | 368 | if (evt == m_EventStopped) 369 | { 370 | 371 | return "Trace stopped"; 372 | } 373 | 374 | return ProfilerEvents.Names[evt.EventClass]; 375 | } // End Function GetEventCaption 376 | 377 | 378 | protected void NewEventArrived(ProfilerEvent evt, bool last) 379 | { 380 | // if (evt == m_EventStarted || evt == m_EventPaused || evt == m_EventStopped) return; 381 | 382 | //m_columns.Add(new PerfColumn { Caption = "Event Class", Column = ProfilerEventColumns.EventClass, Width = 122 }); 383 | //m_columns.Add(new PerfColumn { Caption = "Text Data", Column = ProfilerEventColumns.TextData, Width = 255 }); 384 | //m_columns.Add(new PerfColumn { Caption = "Login Name", Column = ProfilerEventColumns.LoginName, Width = 79 }); 385 | //m_columns.Add(new PerfColumn { Caption = "CPU", Column = ProfilerEventColumns.CPU, Width = 82, Alignment = HorizontalAlignment.Right, Format = "#,0" }); 386 | //m_columns.Add(new PerfColumn { Caption = "Reads", Column = ProfilerEventColumns.Reads, Width = 78, Alignment = HorizontalAlignment.Right, Format = "#,0" }); 387 | //m_columns.Add(new PerfColumn { Caption = "Writes", Column = ProfilerEventColumns.Writes, Width = 78, Alignment = HorizontalAlignment.Right, Format = "#,0" }); 388 | //m_columns.Add(new PerfColumn { Caption = "Duration, ms", Column = ProfilerEventColumns.Duration, Width = 82, Alignment = HorizontalAlignment.Right, Format = "#,0" }); 389 | //m_columns.Add(new PerfColumn { Caption = "SPID", Column = ProfilerEventColumns.SPID, Width = 50, Alignment = HorizontalAlignment.Right }); 390 | //m_columns.Add(new PerfColumn { Caption = "Start time", Column = ProfilerEventColumns.StartTime, Width = 140, Format = "yyyy-MM-ddThh:mm:ss.ffff" }); 391 | //m_columns.Add(new PerfColumn { Caption = "End time", Column = ProfilerEventColumns.EndTime, Width = 140, Format = "yyyy-MM-ddThh:mm:ss.ffff" }); 392 | //m_columns.Add(new PerfColumn { Caption = "DatabaseName", Column = ProfilerEventColumns.DatabaseName, Width = 70 }); 393 | //m_columns.Add(new PerfColumn { Caption = "Object name", Column = ProfilerEventColumns.ObjectName, Width = 70 }); 394 | //m_columns.Add(new PerfColumn { Caption = "Application name", Column = ProfilerEventColumns.ApplicationName, Width = 70 }); 395 | //m_columns.Add(new PerfColumn { Caption = "Host name", Column = ProfilerEventColumns.HostName, Width = 70 }); 396 | 397 | 398 | // System.Console.WriteLine(evt); 399 | System.Console.ResetColor(); 400 | string caption = GetEventCaption(evt); 401 | System.Console.Write(caption); 402 | System.Console.Write(new string(' ', System.Console.BufferWidth - System.Console.CursorLeft)); 403 | 404 | if(!this.m_isWindows) 405 | System.Console.Write(System.Environment.NewLine); 406 | 407 | 408 | 409 | string td = evt.GetFormattedData(ProfilerEventColumns.TextData, null); 410 | // System.Console.WriteLine(td); 411 | 412 | 413 | // System.Windows.Forms.RichTextBox rich, 414 | // RTFBuilder rb = new RTFBuilder { 415 | // BackColor = System.Drawing.Color.White 416 | // }; 417 | // rich.Text = ""; 418 | 419 | 420 | ConsoleOutputWriter cw = new ConsoleOutputWriter(){ 421 | BackColor = System.Drawing.Color.White 422 | }; 423 | 424 | 425 | if (!string.IsNullOrEmpty(td)) 426 | { 427 | // var lex = new YukonLexer(); lex.SyntaxHighlight(cw, td); 428 | this.m_Lex.SyntaxHighlight(cw, td); 429 | // rich.Rtf = this.m_Lex.SyntaxHighlight(rb, td); 430 | } 431 | 432 | // for(int i = 0; i < 65; ++i) // 65 is size of array 433 | // System.Console.WriteLine(evt.GetFormattedData(i, null)); 434 | 435 | //for (int i = 1; i < this.m_columns.Count; ++i) 436 | //{ 437 | // System.Console.WriteLine(i); 438 | // System.Console.WriteLine(this.m_columns[i].Caption); 439 | // System.Console.WriteLine(evt.GetFormattedData(this.m_columns[i].Column, this.m_columns[i].Format)); 440 | //} // Next i 441 | 442 | } // End Sub NewEventArrived 443 | 444 | 445 | } // End Class MyProfiler 446 | 447 | 448 | } // End Namespace ExpressProfiler 449 | -------------------------------------------------------------------------------- /sql_profiler/Code/NotImplemented/TraceProperties.cs: -------------------------------------------------------------------------------- 1 | 2 | // using System.Windows.Forms; 3 | 4 | 5 | namespace ExpressProfiler 6 | { 7 | 8 | 9 | 10 | public partial class TraceProperties // : Form 11 | : System.IDisposable 12 | { 13 | 14 | 15 | public enum StringFilterCondition 16 | { 17 | Like, 18 | NotLike 19 | } 20 | 21 | public enum IntFilterCondition 22 | { 23 | Equal, 24 | NotEqual, 25 | GreaterThan, 26 | LessThan 27 | } 28 | 29 | 30 | public static StringFilterCondition ParseStringCondition(string value) 31 | { 32 | switch (value.ToLower()) 33 | { 34 | case "like": 35 | case "eq": 36 | case "=": return StringFilterCondition.Like; 37 | case "notlike": return StringFilterCondition.NotLike; 38 | } 39 | throw new System.Exception("Unknown filter condition:" + value); 40 | } 41 | 42 | 43 | public static IntFilterCondition ParseIntCondition(string value) 44 | { 45 | switch (value.ToLower()) 46 | { 47 | case "equal": 48 | case "eq": 49 | case "=": 50 | return IntFilterCondition.Equal; 51 | case "notequal": 52 | case "ne": 53 | case "!=": 54 | case "<>": return IntFilterCondition.NotEqual; 55 | case "greaterthan": 56 | case "ge": 57 | case ">": return IntFilterCondition.GreaterThan; 58 | case "lessthan": 59 | case "le": 60 | case "<": return IntFilterCondition.LessThan; 61 | } 62 | throw new System.Exception("Unknown filter condition:" + value); 63 | } 64 | /* 65 | declare @xml xml 66 | set @xml = ' 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | ' 75 | 76 | select ' 77 | [System.ComponentModel.Category(@"'+b.value('@text','varchar(512)')+'")] 78 | [System.ComponentModel.DisplayName(@"Condition")] 79 | public '+b.value('@type','varchar(512)')+'FilterComparison '+replace(b.value('@text','varchar(512)'),' ','')+'FilterComparison { get; set; } 80 | [System.ComponentModel.Category(@"'+b.value('@text','varchar(512)')+'")] 81 | [System.ComponentModel.DisplayName(@"Value")] 82 | public '+lower(b.value('@type','varchar(512)'))+' '+replace(b.value('@text','varchar(512)'),' ','')+ '{ get; set; }' 83 | 84 | from @xml.nodes('/root/r') a(b) 85 | order by b.value('@text','varchar(512)') 86 | */ 87 | 88 | [System.Serializable] 89 | public class TraceSettings 90 | { 91 | public TraceEventsColumns EventsColumns; 92 | public TraceFilters Filters; 93 | 94 | public TraceSettings() 95 | { 96 | 97 | EventsColumns = new TraceEventsColumns 98 | { 99 | BatchCompleted = true, 100 | RPCCompleted = true, 101 | StartTime = true, 102 | EndTime = true 103 | }; 104 | Filters = new TraceFilters 105 | { 106 | MaximumEventCount = 5000, 107 | CpuFilterCondition = IntFilterCondition.GreaterThan, 108 | ReadsFilterCondition = IntFilterCondition.GreaterThan, 109 | WritesFilterCondition = IntFilterCondition.GreaterThan, 110 | DurationFilterCondition = IntFilterCondition.GreaterThan 111 | }; 112 | } 113 | 114 | public string GetAsXmlString() 115 | { 116 | System.Xml.Serialization.XmlSerializer x = 117 | new System.Xml.Serialization.XmlSerializer(typeof(TraceSettings)); 118 | 119 | using (System.IO.StringWriter sw = new System.IO.StringWriter()) 120 | { 121 | x.Serialize(sw, this); 122 | return sw.ToString(); 123 | } 124 | } 125 | 126 | public static TraceSettings GetDefaultSettings() 127 | { 128 | return new TraceSettings { }; 129 | } 130 | 131 | public TraceSettings GetCopy() 132 | { 133 | return new TraceSettings 134 | { 135 | 136 | EventsColumns = new TraceEventsColumns 137 | { 138 | BatchCompleted = EventsColumns.BatchCompleted, 139 | BatchStarting = EventsColumns.BatchStarting, 140 | ExistingConnection = EventsColumns.ExistingConnection, 141 | LoginLogout = EventsColumns.LoginLogout, 142 | RPCCompleted = EventsColumns.RPCCompleted, 143 | RPCStarting = EventsColumns.RPCStarting, 144 | SPStmtCompleted = EventsColumns.SPStmtCompleted, 145 | SPStmtStarting = EventsColumns.SPStmtStarting, 146 | UserErrorMessage = EventsColumns.UserErrorMessage, 147 | ApplicationName = EventsColumns.ApplicationName, 148 | HostName = EventsColumns.HostName, 149 | DatabaseName = EventsColumns.DatabaseName, 150 | EndTime = EventsColumns.EndTime, 151 | ObjectName = EventsColumns.ObjectName, 152 | StartTime = EventsColumns.StartTime, 153 | BlockedProcessPeport = EventsColumns.BlockedProcessPeport, 154 | SQLStmtStarting = EventsColumns.SQLStmtStarting, 155 | SQLStmtCompleted = EventsColumns.SQLStmtCompleted 156 | } 157 | , 158 | Filters = new TraceFilters 159 | { 160 | CPU = Filters.CPU, 161 | CpuFilterCondition = Filters.CpuFilterCondition, 162 | DatabaseName = Filters.DatabaseName, 163 | DatabaseNameFilterCondition = Filters.DatabaseNameFilterCondition, 164 | Duration = Filters.Duration, 165 | DurationFilterCondition = Filters.DurationFilterCondition, 166 | LoginName = Filters.LoginName, 167 | HostName = Filters.HostName, 168 | HostNameFilterCondition = Filters.HostNameFilterCondition, 169 | LoginNameFilterCondition = Filters.LoginNameFilterCondition, 170 | Reads = Filters.Reads, 171 | ReadsFilterCondition = Filters.ReadsFilterCondition, 172 | TextData = Filters.TextData, 173 | TextDataFilterCondition = Filters.TextDataFilterCondition, 174 | Writes = Filters.Writes, 175 | WritesFilterCondition = Filters.WritesFilterCondition, 176 | MaximumEventCount = Filters.MaximumEventCount, 177 | SPID = Filters.SPID, 178 | SPIDFilterCondition = Filters.SPIDFilterCondition, 179 | ApplicationName = Filters.ApplicationName, 180 | ApplicationNameFilterCondition = Filters.ApplicationNameFilterCondition, 181 | 182 | } 183 | } 184 | ; 185 | } 186 | 187 | } 188 | 189 | internal TraceSettings m_currentsettings; 190 | [System.Serializable] 191 | public class TraceEventsColumns 192 | { 193 | [System.ComponentModel.Category(@"Events")] 194 | [System.ComponentModel.DisplayName(@"ExistingConnection")] 195 | [System.ComponentModel.Description(@"The ExistingConnection event class indicates the properties of existing user connections when the trace was started. The server raises one ExistingConnection event per existing user connection.")] 196 | [System.ComponentModel.DefaultValue(false)] 197 | public bool ExistingConnection { get; set; } 198 | [System.ComponentModel.Category(@"Events")] 199 | [System.ComponentModel.DisplayName(@"LoginLogout")] 200 | [System.ComponentModel.Description(@"The Audit Login event class indicates that a user has successfully logged in to SQL Server. Events in this class are fired by new connections or by connections that are reused from a connection pool. The Audit Logout event class indicates that a user has logged out of (logged off) Microsoft SQL Server. Events in this class are fired by new connections or by connections that are reused from a connection pool.")] 201 | [System.ComponentModel.DefaultValue(false)] 202 | public bool LoginLogout { get; set; } 203 | [System.ComponentModel.Category(@"Events")] 204 | [System.ComponentModel.DisplayName(@"RPC:Starting")] 205 | [System.ComponentModel.Description(@"The RPC:Starting event class indicates that a remote procedure call has started.")] 206 | [System.ComponentModel.DefaultValue(false)] 207 | public bool RPCStarting { get; set; } 208 | [System.ComponentModel.Category(@"Events")] 209 | [System.ComponentModel.DisplayName(@"RPC:Completed")] 210 | [System.ComponentModel.Description(@"The RPC:Completed event class indicates that a remote procedure call has been completed. ")] 211 | [System.ComponentModel.DefaultValue(false)] 212 | public bool RPCCompleted { get; set; } 213 | [System.ComponentModel.Category(@"Events")] 214 | [System.ComponentModel.DisplayName(@"SQL:BatchStarting")] 215 | [System.ComponentModel.Description(@"The SQL:BatchStarting event class indicates that a Transact-SQL batch is starting.")] 216 | [System.ComponentModel.DefaultValue(false)] 217 | public bool BatchStarting { get; set; } 218 | [System.ComponentModel.Category(@"Events")] 219 | [System.ComponentModel.DisplayName(@"SQL:BatchCompleted")] 220 | [System.ComponentModel.Description(@"The SQL:BatchCompleted event class indicates that the Transact-SQL batch has completed. ")] 221 | [System.ComponentModel.DefaultValue(false)] 222 | public bool BatchCompleted { get; set; } 223 | [System.ComponentModel.Category(@"Events")] 224 | [System.ComponentModel.DisplayName(@"SP:StmtCompleted")] 225 | [System.ComponentModel.Description(@"The SP:StmtCompleted event class indicates that a Transact-SQL statement within a stored procedure has completed. ")] 226 | [System.ComponentModel.DefaultValue(false)] 227 | public bool SPStmtCompleted { get; set; } 228 | [System.ComponentModel.Category(@"Events")] 229 | [System.ComponentModel.DisplayName(@"SP:StmtStarting")] 230 | [System.ComponentModel.Description(@"The SP:StmtStarting event class indicates that a Transact-SQL statement within a stored procedure has started. ")] 231 | [System.ComponentModel.DefaultValue(false)] 232 | public bool SPStmtStarting { get; set; } 233 | [System.ComponentModel.Category(@"Events")] 234 | [System.ComponentModel.DisplayName(@"User Error Message")] 235 | [System.ComponentModel.Description(@"The User Error Message event class displays the error message as seen by the user in the case of an error or exception. The error message text appears in the TextData field.")] 236 | [System.ComponentModel.DefaultValue(false)] 237 | public bool UserErrorMessage { get; set; } 238 | [System.ComponentModel.Category(@"Events")] 239 | [System.ComponentModel.DisplayName(@"Blocked process report")] 240 | [System.ComponentModel.Description(@"The Blocked Process Report event class indicates that a task has been blocked for more than a specified amount of time. This event class does not include system tasks or tasks that are waiting on non deadlock-detectable resources.")] 241 | [System.ComponentModel.DefaultValue(false)] 242 | public bool BlockedProcessPeport { get; set; } 243 | [System.ComponentModel.Category(@"Events")] 244 | [System.ComponentModel.DisplayName(@"SQL:StmtStarting")] 245 | [System.ComponentModel.Description(@"The SQL:StmtStarting event class indicates that a Transact-SQL statement has started.")] 246 | [System.ComponentModel.DefaultValue(false)] 247 | public bool SQLStmtStarting { get; set; } 248 | [System.ComponentModel.Category(@"Events")] 249 | [System.ComponentModel.DisplayName(@"SQL:StmtCompleted")] 250 | [System.ComponentModel.Description(@"The SQL:StmtCompleted event class indicates that a Transact-SQL statement has completed. ")] 251 | [System.ComponentModel.DefaultValue(false)] 252 | public bool SQLStmtCompleted { get; set; } 253 | 254 | 255 | 256 | 257 | [System.ComponentModel.Category(@"Columns")] 258 | [System.ComponentModel.DisplayName(@"Start time")] 259 | [System.ComponentModel.Description(@"The time at which the event started, when available.")] 260 | [System.ComponentModel.DefaultValue(false)] 261 | public bool StartTime { get; set; } 262 | [System.ComponentModel.Category(@"Columns")] 263 | [System.ComponentModel.DisplayName(@"End time")] 264 | [System.ComponentModel.Description(@"The time at which the event ended. This column is not populated for event classes that refer to an event that is starting, such as SQL:BatchStarting or SP:Starting.")] 265 | [System.ComponentModel.DefaultValue(false)] 266 | public bool EndTime { get; set; } 267 | [System.ComponentModel.Category(@"Columns")] 268 | [System.ComponentModel.DisplayName(@"DatabaseName")] 269 | [System.ComponentModel.Description(@"The name of the database in which the user statement is running.")] 270 | [System.ComponentModel.DefaultValue(false)] 271 | public bool DatabaseName { get; set; } 272 | [System.ComponentModel.Category(@"Columns")] 273 | [System.ComponentModel.DisplayName(@"Application name")] 274 | [System.ComponentModel.Description(@"The name of the client application that created the connection to an instance of SQL Server. This column is populated with the values passed by the application and not the name of the program.")] 275 | [System.ComponentModel.DefaultValue(false)] 276 | public bool ApplicationName { get; set; } 277 | [System.ComponentModel.Category(@"Columns")] 278 | [System.ComponentModel.DisplayName(@"Object name")] 279 | [System.ComponentModel.Description(@"The name of the object that is referenced.")] 280 | [System.ComponentModel.DefaultValue(false)] 281 | public bool ObjectName { get; set; } 282 | [System.ComponentModel.Category(@"Columns")] 283 | [System.ComponentModel.DisplayName(@"Host name")] 284 | [System.ComponentModel.Description(@"Name of the client computer that originated the request.")] 285 | [System.ComponentModel.DefaultValue(false)] 286 | public bool HostName { get; set; } 287 | 288 | } 289 | 290 | 291 | 292 | [System.Serializable] 293 | public class TraceFilters 294 | { 295 | 296 | [System.ComponentModel.Category(@"CPU")] 297 | [System.ComponentModel.DisplayName(@"Condition")] 298 | public IntFilterCondition CpuFilterCondition { get; set; } 299 | [System.ComponentModel.Category(@"CPU")] 300 | [System.ComponentModel.DisplayName(@"Value")] 301 | public int? CPU { get; set; } 302 | 303 | [System.ComponentModel.Category(@"DatabaseName")] 304 | [System.ComponentModel.DisplayName(@"Condition")] 305 | public StringFilterCondition DatabaseNameFilterCondition { get; set; } 306 | [System.ComponentModel.Category(@"DatabaseName")] 307 | [System.ComponentModel.DisplayName(@"Value")] 308 | public string DatabaseName { get; set; } 309 | 310 | [System.ComponentModel.Category(@"Duration")] 311 | [System.ComponentModel.DisplayName(@"Condition")] 312 | public IntFilterCondition DurationFilterCondition { get; set; } 313 | [System.ComponentModel.Category(@"Duration")] 314 | [System.ComponentModel.DisplayName(@"Value")] 315 | public int? Duration { get; set; } 316 | 317 | [System.ComponentModel.Category(@"LoginName")] 318 | [System.ComponentModel.DisplayName(@"Condition")] 319 | public StringFilterCondition LoginNameFilterCondition { get; set; } 320 | [System.ComponentModel.Category(@"LoginName")] 321 | [System.ComponentModel.DisplayName(@"Value")] 322 | public string LoginName { get; set; } 323 | 324 | [System.ComponentModel.Category(@"HostName")] 325 | [System.ComponentModel.DisplayName(@"Condition")] 326 | public StringFilterCondition HostNameFilterCondition { get; set; } 327 | [System.ComponentModel.Category(@"HostName")] 328 | [System.ComponentModel.DisplayName(@"Value")] 329 | public string HostName { get; set; } 330 | 331 | 332 | [System.ComponentModel.Category(@"Reads")] 333 | [System.ComponentModel.DisplayName(@"Condition")] 334 | public IntFilterCondition ReadsFilterCondition { get; set; } 335 | [System.ComponentModel.Category(@"Reads")] 336 | [System.ComponentModel.DisplayName(@"Value")] 337 | public int? Reads { get; set; } 338 | 339 | [System.ComponentModel.Category(@"TextData")] 340 | [System.ComponentModel.DisplayName(@"Condition")] 341 | public StringFilterCondition TextDataFilterCondition { get; set; } 342 | [System.ComponentModel.Category(@"TextData")] 343 | [System.ComponentModel.DisplayName(@"Value")] 344 | public string TextData { get; set; } 345 | 346 | [System.ComponentModel.Category(@"Writes")] 347 | [System.ComponentModel.DisplayName(@"Condition")] 348 | public IntFilterCondition WritesFilterCondition { get; set; } 349 | 350 | [System.ComponentModel.Category(@"Writes")] 351 | [System.ComponentModel.DisplayName(@"Value")] 352 | public int? Writes { get; set; } 353 | 354 | [System.ComponentModel.Category(@"Maximum events count")] 355 | [System.ComponentModel.DisplayName(@"Maximum events count")] 356 | // [System.ComponentModel.DefaultValue(5000)] 357 | public int MaximumEventCount { get; set; } 358 | 359 | [System.ComponentModel.Category(@"SPID")] 360 | [System.ComponentModel.DisplayName(@"Condition")] 361 | public IntFilterCondition SPIDFilterCondition { get; set; } 362 | [System.ComponentModel.Category(@"SPID")] 363 | [System.ComponentModel.DisplayName(@"Value")] 364 | public int? SPID { get; set; } 365 | 366 | [System.ComponentModel.Category(@"ApplicationName")] 367 | [System.ComponentModel.DisplayName(@"Condition")] 368 | public StringFilterCondition ApplicationNameFilterCondition { get; set; } 369 | [System.ComponentModel.Category(@"ApplicationName")] 370 | [System.ComponentModel.DisplayName(@"Value")] 371 | public string ApplicationName { get; set; } 372 | 373 | } 374 | 375 | public TraceProperties() 376 | { 377 | // InitializeComponent(); 378 | } 379 | 380 | public void SetSettings(TraceSettings st) 381 | { 382 | m_currentsettings = st; 383 | // edEvents.SelectedObject = m_currentsettings.EventsColumns; 384 | // edFilters.SelectedObject = m_currentsettings.Filters; 385 | } 386 | 387 | private void btnReset_Click(object sender, System.EventArgs e) 388 | { 389 | SetSettings(TraceSettings.GetDefaultSettings()); 390 | } 391 | 392 | private void btnSaveAsDefault_Click(object sender, System.EventArgs e) 393 | { 394 | // Properties.Settings.Default.TraceSettings = m_currentsettings.GetAsXmlString(); 395 | // Properties.Settings.Default.Save(); 396 | } 397 | 398 | 399 | internal static bool AtLeastOneEventSelected(TraceSettings ts) 400 | { 401 | return ts.EventsColumns.BatchCompleted 402 | || ts.EventsColumns.BatchStarting 403 | || ts.EventsColumns.LoginLogout 404 | || ts.EventsColumns.ExistingConnection 405 | || ts.EventsColumns.RPCCompleted 406 | || ts.EventsColumns.RPCStarting 407 | || ts.EventsColumns.SPStmtCompleted 408 | || ts.EventsColumns.SPStmtStarting 409 | || ts.EventsColumns.UserErrorMessage 410 | || ts.EventsColumns.BlockedProcessPeport 411 | || ts.EventsColumns.SQLStmtStarting 412 | || ts.EventsColumns.SQLStmtCompleted; 413 | 414 | } 415 | 416 | private void btnRun_Click(object sender, System.EventArgs e) 417 | { 418 | if (!AtLeastOneEventSelected(m_currentsettings)) 419 | { 420 | System.Console.WriteLine("Error Starting trace: You should select at least 1 event"); 421 | 422 | // tabControl1.SelectedTab = tabPage2; 423 | return; 424 | } 425 | // DialogResult = DialogResult.OK; 426 | } 427 | 428 | /* 429 | public bool IsIncluded(ListViewItem lvi) 430 | { 431 | bool included = true; 432 | 433 | //Fragile here to hard coding the columns, but they are currently this way. 434 | included &= IsIncluded(m_currentsettings.Filters.ApplicationNameFilterCondition, m_currentsettings.Filters.ApplicationName, lvi.SubItems[0].Text); 435 | included &= IsIncluded(m_currentsettings.Filters.TextDataFilterCondition, m_currentsettings.Filters.TextData, lvi.SubItems[1].Text); 436 | included &= IsIncluded(m_currentsettings.Filters.LoginNameFilterCondition, m_currentsettings.Filters.LoginName, lvi.SubItems[2].Text); 437 | included &= IsIncluded(m_currentsettings.Filters.CpuFilterCondition, m_currentsettings.Filters.CPU, lvi.SubItems[3].Text); 438 | included &= IsIncluded(m_currentsettings.Filters.ReadsFilterCondition, m_currentsettings.Filters.Reads, lvi.SubItems[4].Text); 439 | included &= IsIncluded(m_currentsettings.Filters.WritesFilterCondition, m_currentsettings.Filters.Writes, lvi.SubItems[5].Text); 440 | included &= IsIncluded(m_currentsettings.Filters.DurationFilterCondition, m_currentsettings.Filters.Duration, lvi.SubItems[6].Text); 441 | included &= IsIncluded(m_currentsettings.Filters.SPIDFilterCondition, m_currentsettings.Filters.SPID, lvi.SubItems[7].Text); 442 | 443 | return included; 444 | } 445 | */ 446 | 447 | 448 | private bool IsIncluded(StringFilterCondition filterCondition, string filter, string entryToCheck) 449 | { 450 | bool included = true; //Until removed. Negative logic is applied here. 451 | if (string.IsNullOrEmpty(filter) == false) 452 | { 453 | if (filterCondition == StringFilterCondition.Like) 454 | { 455 | if (entryToCheck.Contains(filter) == false) 456 | { 457 | included = false; 458 | } 459 | } 460 | else if (filterCondition == StringFilterCondition.NotLike) 461 | { 462 | if (entryToCheck.Contains(filter) == true) 463 | { 464 | included = false; 465 | } 466 | } 467 | } 468 | return included; 469 | } 470 | 471 | 472 | private bool IsIncluded(IntFilterCondition filterCondition, int? filter, string entryToCheck) 473 | { 474 | bool included = true; //Until removed. Negative logic is applied here. 475 | 476 | int intEntry; 477 | if ((int.TryParse(entryToCheck, out intEntry)) && (filter.HasValue)) 478 | { 479 | if (filterCondition == IntFilterCondition.Equal) 480 | { 481 | if (filter != intEntry) 482 | { 483 | included = false; 484 | } 485 | } 486 | else if (filterCondition == IntFilterCondition.GreaterThan) 487 | { 488 | if (filter >= intEntry) // <= because we are using negative logic here. 489 | { 490 | included = false; 491 | } 492 | } 493 | else if (filterCondition == IntFilterCondition.LessThan) 494 | { 495 | if (filter <= intEntry) // >= because we are using negative logic here. 496 | { 497 | included = false; 498 | } 499 | } 500 | else if (filterCondition == IntFilterCondition.NotEqual) 501 | { 502 | if (filter == intEntry) 503 | { 504 | included = false; 505 | } 506 | } 507 | } 508 | return included; 509 | } 510 | 511 | #region IDisposable Support 512 | private bool disposedValue = false; // Dient zur Erkennung redundanter Aufrufe. 513 | 514 | protected virtual void Dispose(bool disposing) 515 | { 516 | if (!disposedValue) 517 | { 518 | if (disposing) 519 | { 520 | // TODO: verwalteten Zustand (verwaltete Objekte) entsorgen. 521 | } 522 | 523 | // TODO: nicht verwaltete Ressourcen (nicht verwaltete Objekte) freigeben und Finalizer weiter unten überschreiben. 524 | // TODO: große Felder auf Null setzen. 525 | 526 | disposedValue = true; 527 | } 528 | } 529 | 530 | // TODO: Finalizer nur überschreiben, wenn Dispose(bool disposing) weiter oben Code für die Freigabe nicht verwalteter Ressourcen enthält. 531 | // ~TraceProperties() { 532 | // // Ändern Sie diesen Code nicht. Fügen Sie Bereinigungscode in Dispose(bool disposing) weiter oben ein. 533 | // Dispose(false); 534 | // } 535 | 536 | // Dieser Code wird hinzugefügt, um das Dispose-Muster richtig zu implementieren. 537 | void System.IDisposable.Dispose() 538 | { 539 | // Ändern Sie diesen Code nicht. Fügen Sie Bereinigungscode in Dispose(bool disposing) weiter oben ein. 540 | Dispose(true); 541 | // TODO: Auskommentierung der folgenden Zeile aufheben, wenn der Finalizer weiter oben überschrieben wird. 542 | // GC.SuppressFinalize(this); 543 | } 544 | #endregion 545 | } 546 | } 547 | --------------------------------------------------------------------------------