diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..b160b2e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,17 @@ +name: Build ScriptDomSamples +on: pull_request + +jobs: + build: + runs-on: windows-latest + steps: + - name: Checkout Code + uses: actions/checkout@v2.3.5 + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.0.3 + - name: Setup NuGet + uses: NuGet/setup-nuget@v1.0.5 + - name: Restore NuGet Packages + run: nuget restore ScriptDOMSamples.sln + - name: Build ScriptDOMSamples + run: msbuild ScriptDOMSamples.sln /p:Configuration=Release diff --git a/.gitignore b/.gitignore index 451ae56..d111ad4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,101 @@ /4_TSQLValidation/obj/x86/Debug /5_TSQLFormatter/obj/x86/Debug /6_TSQLVisualizer/obj/x86/Debug +/1_BasicUsage/obj/Debug +/2_VisitorPattern/bin/Debug +/2_VisitorPattern/obj/Debug +/3_ScriptTokens/obj/Debug +/4_TSQLValidation/bin/Debug +/4_TSQLValidation/obj/Debug/TempPE +/4_TSQLValidation/obj/Debug +/5_TSQLFormatter/obj/Debug +/6_TSQLVisualizer/bin/Debug +/6_TSQLVisualizer/obj/Debug +/packages +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates +*.userprefs +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ +.vs/ +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* +*.VisualState.xml +nunit-*.xml +[Dd]ebugPS/ +[Rr]eleasePS/ +StyleCopReport.xml +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc +_Chutzpah* +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.psess +*.vsp +*.vspx +*.sap +*.e2e +$tf/ +*.gpState +*.DotSettings.user +*.dotCover +*.mm.* +*.nupkg +*.snupkg +**/[Pp]ackages/* +!**/[Pp]ackages/build/ +*.nuget.props +*.nuget.targets +*.[Cc]ache +!?*.[Cc]ache/ +~$* +*~ +*.pfx +*.publishsettings +UpgradeLog*.XML +UpgradeLog*.htm + diff --git a/1_BasicUsage/1_BasicUsage.csproj b/1_BasicUsage/1_BasicUsage.csproj index caa3585..cc3d90c 100644 --- a/1_BasicUsage/1_BasicUsage.csproj +++ b/1_BasicUsage/1_BasicUsage.csproj @@ -1,5 +1,5 @@  - + Debug x86 @@ -10,8 +10,9 @@ Properties BasicUsage BasicUsage - v4.0 - Client + v4.8 + + 512 @@ -23,6 +24,7 @@ DEBUG;TRACE prompt 4 + false x86 @@ -32,24 +34,43 @@ TRACE prompt 4 + false + + + true + bin\Debug\ + DEBUG;TRACE + full + AnyCPU + 7.3 + prompt + MinimumRecommendedRules.ruleset + false + + + bin\Release\ + TRACE + true + pdbonly + AnyCPU + 7.3 + prompt + MinimumRecommendedRules.ruleset + false - - False - ..\..\..\Program Files (x86)\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.TransactSql.ScriptDom.dll + + ..\packages\Microsoft.SqlServer.TransactSql.ScriptDom.161.8812.0\lib\net462\Microsoft.SqlServer.TransactSql.ScriptDom.dll - - - - - - - + + + + + \ No newline at end of file diff --git a/7_StatementLists/Form1.Designer.cs b/7_StatementLists/Form1.Designer.cs new file mode 100644 index 0000000..53ec118 --- /dev/null +++ b/7_StatementLists/Form1.Designer.cs @@ -0,0 +1,75 @@ +namespace SQLScriptDomSamples +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.textBox1.Location = new System.Drawing.Point(12, 12); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(781, 384); + this.textBox1.TabIndex = 0; + this.textBox1.WordWrap = false; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(375, 413); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(51, 23); + this.button1.TabIndex = 1; + this.button1.Text = "GO!"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(805, 448); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox1); + this.Name = "Form1"; + this.Text = "T-SQL validator"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + } +} + diff --git a/7_StatementLists/Form1.cs b/7_StatementLists/Form1.cs new file mode 100644 index 0000000..58f627b --- /dev/null +++ b/7_StatementLists/Form1.cs @@ -0,0 +1,142 @@ +//------------------------------------------------------------------------------ +// The MIT License (MIT) +// +// Copyright (c) Arvind Shyamsundar +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// This sample code is not supported under any Microsoft standard support program or service. +// The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. +// In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts +// be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, +// business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability +// to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages. +//------------------------------------------------------------------------------ + +using Microsoft.SqlServer.TransactSql.ScriptDom; +using System; +using System.Collections.Generic; +using System.IO; +using System.Windows.Forms; + +namespace SQLScriptDomSamples +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + using (var rdr = new StringReader(textBox1.Text)) + { + IList errors = null; + var parser = new TSql160Parser(true, SqlEngineType.All); + var tree = parser.Parse(rdr, out errors); + + foreach (ParseError err in errors) + { + Console.WriteLine(err.Message); + } + + var checker = new MyVisitor(); + + tree.Accept(checker); + + var scrGen = new Sql150ScriptGenerator(); + string formattedSQL = null; + scrGen.GenerateScript(tree, out formattedSQL); + + MessageBox.Show(formattedSQL); + } + } + } + + class MyVisitor : TSqlFragmentVisitor + { + internal bool containsOnlySelects = true; + + public override void Visit(TSqlFragment node) + { + // We use this to check for, and remove any SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED statements + // Also, as a proof of concept, the visitor also introduces a SET NOCOUNT ON statement as the first statement + // We do this for TSqlBatch, TSqlProcedure as samples. + // Other fragment types are potentially extensions of this sample. + CheckandRewrite(node); + base.Visit(node); + } + + private void CheckandRewrite(TSqlFragment node) + { + var finalList = new List(); + var toRemoveList = new List(); + + IList stmtList = null; + if (node is TSqlBatch) + { + stmtList = (node as TSqlBatch).Statements; + } + + if (node is ProcedureStatementBodyBase) + { + stmtList = (node as CreateProcedureStatement).StatementList.Statements; + } + + if (stmtList is null) + { + return; + } + + foreach (TSqlStatement stmt in stmtList) + { + if (stmt is SetTransactionIsolationLevelStatement) + { + if (IsolationLevel.ReadUncommitted == + (stmt as SetTransactionIsolationLevelStatement).Level) + { + toRemoveList.Add(stmt); + } + } + } + + // Add a SET NOCOUNT ON statement + finalList.Add(new PredicateSetStatement() + { + Options = SetOptions.NoCount, + IsOn = true + }); + + // Remove any unwanted (SET TRANSACTION ISOLATION READ UNCOMMITTED) statements + foreach (var stmtToRemove in toRemoveList) + { + stmtList.Remove(stmtToRemove); + } + + finalList.AddRange(stmtList); + + stmtList.Clear(); + foreach(var stmt in finalList) + { + stmtList.Add(stmt); + } + } + } +} diff --git a/7_StatementLists/Form1.resx b/7_StatementLists/Form1.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/7_StatementLists/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/7_StatementLists/Program.cs b/7_StatementLists/Program.cs new file mode 100644 index 0000000..3f688bf --- /dev/null +++ b/7_StatementLists/Program.cs @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------------ +// The MIT License (MIT) +// +// Copyright (c) Arvind Shyamsundar +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// This sample code is not supported under any Microsoft standard support program or service. +// The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. +// In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts +// be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, +// business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability +// to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages. +//------------------------------------------------------------------------------ + +using System; +using System.Windows.Forms; + +namespace SQLScriptDomSamples +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/7_StatementLists/Properties/AssemblyInfo.cs b/7_StatementLists/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9095f36 --- /dev/null +++ b/7_StatementLists/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TSQLFormatter")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TSQLFormatter")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ad18d6d1-7875-4cfc-9128-149418db16b4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/7_StatementLists/Properties/Resources.Designer.cs b/7_StatementLists/Properties/Resources.Designer.cs new file mode 100644 index 0000000..43d490c --- /dev/null +++ b/7_StatementLists/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SQLScriptDomSamples.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TSQLFormatter.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/7_StatementLists/Properties/Resources.resx b/7_StatementLists/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/7_StatementLists/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/7_StatementLists/Properties/Settings.Designer.cs b/7_StatementLists/Properties/Settings.Designer.cs new file mode 100644 index 0000000..a4f99f6 --- /dev/null +++ b/7_StatementLists/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SQLScriptDomSamples.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/7_StatementLists/Properties/Settings.settings b/7_StatementLists/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/7_StatementLists/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/7_StatementLists/app.config b/7_StatementLists/app.config new file mode 100644 index 0000000..3dbff35 --- /dev/null +++ b/7_StatementLists/app.config @@ -0,0 +1,3 @@ + + + diff --git a/7_StatementLists/packages.config b/7_StatementLists/packages.config new file mode 100644 index 0000000..14c877b --- /dev/null +++ b/7_StatementLists/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/8_TSQLTextNormalizer/8_TSQLTextNormalizer.csproj b/8_TSQLTextNormalizer/8_TSQLTextNormalizer.csproj new file mode 100644 index 0000000..45aaf92 --- /dev/null +++ b/8_TSQLTextNormalizer/8_TSQLTextNormalizer.csproj @@ -0,0 +1,66 @@ + + + + + Debug + AnyCPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7} + Exe + Properties + TSQLTextNormalizer + TSQLTextNormalizer + v4.8 + 512 + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microsoft.SqlServer.TransactSql.ScriptDom.161.8812.0\lib\net462\Microsoft.SqlServer.TransactSql.ScriptDom.dll + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/8_TSQLTextNormalizer/App.config b/8_TSQLTextNormalizer/App.config new file mode 100644 index 0000000..4bfa005 --- /dev/null +++ b/8_TSQLTextNormalizer/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/8_TSQLTextNormalizer/Program.cs b/8_TSQLTextNormalizer/Program.cs new file mode 100644 index 0000000..22e6e0d --- /dev/null +++ b/8_TSQLTextNormalizer/Program.cs @@ -0,0 +1,98 @@ +//------------------------------------------------------------------------------ +// The MIT License (MIT) +// +// Copyright (c) Arvind Shyamsundar +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// This sample code is not supported under any Microsoft standard support program or service. +// The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. +// In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts +// be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, +// business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability +// to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages. +//------------------------------------------------------------------------------ +// +// This example shows how to use the TransactSql.ScriptDom parser to 'normalize' batch text and retain only unique query patterns +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace SQLScriptDomSamples +{ + using System; + using System.IO; + + class Program + { + static void Main(string[] args) + { + // Parameters we expect: + // .SQL filename to normalize + // output filename + // compat level (80...160) + // whether to treat the batches as case sensitive (true / false) + + if (4 != args.Length) + { + WriteMessageAndExit("Usage: Normalize "); + } + + if (!File.Exists(args[0])) + { + WriteMessageAndExit("Input file was not found; exiting."); + } + + if (File.Exists(args[1])) + { + Console.Write("Output file already exists. Overwrite? Press Y or N."); + char decision = Console.ReadKey().KeyChar; + if (string.Equals(decision.ToString(), "n", StringComparison.CurrentCultureIgnoreCase)) + { + WriteMessageAndExit("You selected not to overwrite; exiting."); + } + } + + int compatLevel = 160; + if (!int.TryParse(args[2], out compatLevel)) + { + WriteMessageAndExit("Invalid value for compatibility level. Valid values range from 80 to 160."); + } + + Console.WriteLine(); + + using (var input = new FileStream(args[0], FileMode.Open)) + { + using (var output = new FileStream(args[1], FileMode.Create)) + { + bool caseSensitive = true; + bool.TryParse(args[3], out caseSensitive); + + Console.WriteLine(new TSqlNormalizer().Normalize(input, output, compatLevel, caseSensitive)); + Console.WriteLine("Done!"); + } + } + } + + private static void WriteMessageAndExit(string msg) + { + Console.WriteLine(msg); + Environment.Exit(1); + } + } +} diff --git a/8_TSQLTextNormalizer/Properties/AssemblyInfo.cs b/8_TSQLTextNormalizer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..2ab8e00 --- /dev/null +++ b/8_TSQLTextNormalizer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TSQLTextNormalizer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TSQLTextNormalizer")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("15c5cd8a-d960-4f45-a6ad-b3b13f9719c5")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/8_TSQLTextNormalizer/TSqlNormalizer.cs b/8_TSQLTextNormalizer/TSqlNormalizer.cs new file mode 100644 index 0000000..600db20 --- /dev/null +++ b/8_TSQLTextNormalizer/TSqlNormalizer.cs @@ -0,0 +1,213 @@ +//------------------------------------------------------------------------------ +// The MIT License (MIT) +// +// Copyright (c) Arvind Shyamsundar +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// This sample code is not supported under any Microsoft standard support program or service. +// The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. +// In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts +// be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, +// business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability +// to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages. +//------------------------------------------------------------------------------ +namespace SQLScriptDomSamples +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Security.Cryptography; + using System.Text; + using System.Threading.Tasks; + + using Microsoft.SqlServer.TransactSql.ScriptDom; + + internal class TSqlNormalizer + { + internal string Normalize(Stream input, Stream output, int compatLevel, bool caseSensitive) + { + string retVal = string.Empty; + + Dictionary normalizedBatches = new Dictionary(); + + TextReader rdr = new StreamReader(input); + + TSqlParser parser; + + SqlScriptGenerator scrgen = null; + + switch (compatLevel) + { + case 80: + { + scrgen = new Sql80ScriptGenerator(); + parser = new TSql80Parser(true); + break; + } + case 90: + { + scrgen = new Sql90ScriptGenerator(); + parser = new TSql90Parser(true); + break; + } + case 100: + { + scrgen = new Sql100ScriptGenerator(); + parser = new TSql100Parser(true); + break; + } + case 110: + { + scrgen = new Sql110ScriptGenerator(); + parser = new TSql110Parser(true); + break; + } + case 120: + { + scrgen = new Sql120ScriptGenerator(); + parser = new TSql120Parser(true); + break; + } + case 130: + { + scrgen = new Sql130ScriptGenerator(); + parser = new TSql130Parser(true); + break; + } + case 140: + { + scrgen = new Sql140ScriptGenerator(); + parser = new TSql140Parser(true); + break; + } + case 150: + { + scrgen = new Sql150ScriptGenerator(); + parser = new TSql160Parser(true); + break; + } + case 160: + { + scrgen = new Sql160ScriptGenerator(); + parser = new TSql160Parser(true); + break; + } + default: + { + return "Invalid compatibility level specified; exiting."; + } + } + + IList errs; + TSqlFragment frag = parser.Parse(rdr, out errs); + + StringBuilder sb = new StringBuilder(); + foreach (ParseError err in errs) + { + sb.AppendLine(err.Message + "@ line " + err.Line); + } + + retVal += sb.ToString(); + + Parallel.ForEach( + (frag as TSqlScript).Batches, + batch => + { + myvisitor visit = new myvisitor(); + + StringBuilder origscript = new StringBuilder(); + + for (int tokIdx = batch.FirstTokenIndex; tokIdx <= batch.LastTokenIndex; tokIdx++) + { + origscript.Append(batch.ScriptTokenStream[tokIdx].Text); + } + + batch.Accept(visit); + + string script; + + scrgen.GenerateScript(batch, out script); + + string hashValue; + + using (var hashProvider = new SHA1CryptoServiceProvider()) + { + if (caseSensitive) + { + hashValue = Convert.ToBase64String(hashProvider.ComputeHash(Encoding.Unicode.GetBytes(script))); + } + else + { + hashValue = Convert.ToBase64String(hashProvider.ComputeHash(Encoding.Unicode.GetBytes(script.ToLowerInvariant()))); + } + } + + lock (normalizedBatches) + { + if (normalizedBatches.ContainsKey(hashValue)) + { + normalizedBatches[hashValue].count++; + } + else + { + normalizedBatches.Add( + hashValue, + new Batch() { count = 1, normalizedText = script, sample = origscript.ToString() }); + } + } + }); + + // The normalized (tokenized) text is in the Batch.text member above. The below writes that out to a file + var p = from b in normalizedBatches.Keys select new { hash = b, count = normalizedBatches[b] }; + + StringBuilder sbfinal = new StringBuilder(); + + foreach (string key in normalizedBatches.Keys) + { + string final = string.Format( + "-- {0} times:\r\n{1}", + normalizedBatches[key].count, + normalizedBatches[key].normalizedText); + + sbfinal.AppendLine(final); + sbfinal.AppendLine("GO"); + sbfinal.AppendLine(); + } + + TextWriter wr = new StreamWriter(output); + wr.Write(sbfinal.ToString()); + wr.Flush(); + wr.Dispose(); + wr = null; + + return retVal; + } + } + + internal class Batch + { + public string normalizedText; + + public string sample; + + public int count; + } +} diff --git a/8_TSQLTextNormalizer/TSqlVisitor.cs b/8_TSQLTextNormalizer/TSqlVisitor.cs new file mode 100644 index 0000000..1420394 --- /dev/null +++ b/8_TSQLTextNormalizer/TSqlVisitor.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// The MIT License (MIT) +// +// Copyright (c) Arvind Shyamsundar +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// This sample code is not supported under any Microsoft standard support program or service. +// The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. +// In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts +// be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, +// business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability +// to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages. +//------------------------------------------------------------------------------ +namespace SQLScriptDomSamples +{ + using Microsoft.SqlServer.TransactSql.ScriptDom; + + class myvisitor : TSqlFragmentVisitor + { + public override void ExplicitVisit(InPredicate node) + { + int numvalues = node.Values.Count; + if (numvalues > 1) + { + for (int i = numvalues - 1; i > 0; i--) + { + if (node.Values[i] is Literal) + { + node.Values.RemoveAt(i); + } + } + } + + base.ExplicitVisit(node); + } + + public override void ExplicitVisit(NumericLiteral node) + { + node.Value = "0.1"; + base.ExplicitVisit(node); + } + + public override void ExplicitVisit(MoneyLiteral node) + { + node.Value = "$1"; + base.ExplicitVisit(node); + } + + public override void ExplicitVisit(BinaryLiteral node) + { + node.Value = "0xABCD"; + base.ExplicitVisit(node); + } + + public override void ExplicitVisit(RealLiteral node) + { + node.Value = "0.5E-2"; + base.ExplicitVisit(node); + } + + public override void ExplicitVisit(IntegerLiteral node) + { + node.Value = "0"; + base.ExplicitVisit(node); + } + + public override void ExplicitVisit(StringLiteral node) + { + node.Value = "foo"; + base.ExplicitVisit(node); + } + } +} diff --git a/8_TSQLTextNormalizer/packages.config b/8_TSQLTextNormalizer/packages.config new file mode 100644 index 0000000..14c877b --- /dev/null +++ b/8_TSQLTextNormalizer/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/9_TSQLRewrite/9_TSQLRewrite.csproj b/9_TSQLRewrite/9_TSQLRewrite.csproj new file mode 100644 index 0000000..8286645 --- /dev/null +++ b/9_TSQLRewrite/9_TSQLRewrite.csproj @@ -0,0 +1,64 @@ + + + + + Debug + AnyCPU + {303F7887-FC8F-4237-AE88-39F81AF9274E} + Exe + Properties + TSQLRewrite + TSQLRewrite + v4.8 + 512 + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microsoft.SqlServer.TransactSql.ScriptDom.161.8812.0\lib\net462\Microsoft.SqlServer.TransactSql.ScriptDom.dll + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/9_TSQLRewrite/App.config b/9_TSQLRewrite/App.config new file mode 100644 index 0000000..4bfa005 --- /dev/null +++ b/9_TSQLRewrite/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/9_TSQLRewrite/Program.cs b/9_TSQLRewrite/Program.cs new file mode 100644 index 0000000..cbe24a2 --- /dev/null +++ b/9_TSQLRewrite/Program.cs @@ -0,0 +1,105 @@ +//------------------------------------------------------------------------------ +// The MIT License (MIT) +// +// Copyright (c) Arvind Shyamsundar +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// This sample code is not supported under any Microsoft standard support program or service. +// The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. +// In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts +// be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, +// business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability +// to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages. +//------------------------------------------------------------------------------ +// +// This example shows how to use the TransactSql.ScriptDom parser to potentially change script tokens +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace SQLScriptDomSamples +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using Microsoft.SqlServer.TransactSql.ScriptDom; + + class Program + { + static void Main(string[] args) + { + using (var rdr = new StreamReader(@"..\..\..\sampleproc.sql")) + { + IList errors = null; + var parser = new TSql150Parser(true, SqlEngineType.All); + var tree = parser.Parse(rdr, out errors); + + foreach (ParseError err in errors) + { + Console.WriteLine(err.Message); + } + + Console.WriteLine("Example of replacing tokens:"); + Console.WriteLine("============================"); + + // access, manipulate, and then print the script tokens + // this first loop is very simple, it just replaces < sign with > sign + for (int tmpLoop = tree.FirstTokenIndex; tmpLoop <= tree.LastTokenIndex; tmpLoop++) + { + if (tree.ScriptTokenStream[tmpLoop].TokenType == TSqlTokenType.LessThan) + { + //Console.WriteLine(string.Format("Token {0} is a 'less than' sign; changing it to 'greater than' sign", tmpLoop)); + tree.ScriptTokenStream[tmpLoop].TokenType = TSqlTokenType.GreaterThan; + tree.ScriptTokenStream[tmpLoop].Text = ">"; + } + + // print the output, which would include the re-written token + Console.Write(tree.ScriptTokenStream[tmpLoop].Text); + } + + Console.WriteLine("Example of dropping and injecting multiple tokens:"); + Console.WriteLine("=================================================="); + + // access, manipulate, and then print the script tokens + // this second loop is shows how to potentially delete and inject new tokens and build a new stream + // given we already modified the < sign to a > sign in the previous loop, we will look for a > sign + // and replace it with a >= sign + var outTokens = new List(); + for (int tmpLoop = tree.FirstTokenIndex; tmpLoop <= tree.LastTokenIndex; tmpLoop++) + { + if (tree.ScriptTokenStream[tmpLoop].TokenType == TSqlTokenType.GreaterThan) + { + //Console.WriteLine(string.Format("Token {0} is a 'less than' sign; dropping and injecting a 'greater than equal to' sign in the output", tmpLoop)); + // we ignore the original token and inject two tokens in the output; > and = + outTokens.Add(new TSqlParserToken(TSqlTokenType.GreaterThan, ">")); + outTokens.Add(new TSqlParserToken(TSqlTokenType.EqualsSign, "=")); + } + else + { + // add the token as-is + outTokens.Add(tree.ScriptTokenStream[tmpLoop]); + } + } + // print the output, which would include the re-written token + Console.Write(string.Join(string.Empty, outTokens.Select(t => t.Text))); + } + } + } +} diff --git a/9_TSQLRewrite/Properties/AssemblyInfo.cs b/9_TSQLRewrite/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b001029 --- /dev/null +++ b/9_TSQLRewrite/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TSQLRewrite")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TSQLRewrite")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("15c5cd8a-d960-4f45-a6ad-b3b13f9719c5")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/9_TSQLRewrite/packages.config b/9_TSQLRewrite/packages.config new file mode 100644 index 0000000..14c877b --- /dev/null +++ b/9_TSQLRewrite/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2186590 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2020 Arvind Shyamsundar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..17739b5 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# SQLScriptDomSamples +These samples are a quick set of scenarios showing how to use Microsoft.SqlServer.TransactSql.ScriptDom classes. They were originally created to support a PASS AppDev virtual chapter meeting - [video recording](https://www.youtube.com/watch?v=CciVxRFXgH8). diff --git a/SampleProc.sql b/SampleProc.sql index e70898e..741e6d4 100644 --- a/SampleProc.sql +++ b/SampleProc.sql @@ -1,3 +1,4 @@ +-- Some leading comments with < and > signs to test for later CREATE PROCEDURE [HumanResources].[uspUpdateEmployeeHireInfo] @BusinessEntityID [int], @JobTitle [nvarchar](50), @@ -32,7 +33,7 @@ BEGIN BEGIN CATCH -- Rollback any active or uncommittable transactions before -- inserting information in the ErrorLog - IF @@TRANCOUNT > 0 + IF @@TRANCOUNT > 0 and 0 < 1 BEGIN ROLLBACK TRANSACTION; END diff --git a/ScriptDOMSamples.sln b/ScriptDOMSamples.sln index 0fe051f..06d620d 100644 --- a/ScriptDOMSamples.sln +++ b/ScriptDOMSamples.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32210.238 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "1_BasicUsage", "1_BasicUsage\1_BasicUsage.csproj", "{88301D6F-7C0B-4950-891D-999F991133A6}" EndProject @@ -15,38 +15,145 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "5_TSQLFormatter", "5_TSQLFo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "6_TSQLVisualizer", "6_TSQLVisualizer\6_TSQLVisualizer.csproj", "{51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "7_StatementLists", "7_StatementLists\7_StatementLists.csproj", "{82E6E27C-2B4D-4D83-A797-18EBF1F721F2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{A19B07A2-A103-4BC5-9705-F8C01FCE3C5D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{698BF626-CEC2-4FAF-80A3-40D515134A54}" + ProjectSection(SolutionItems) = preProject + .github\workflows\build.yml = .github\workflows\build.yml + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "8_TSQLTextNormalizer", "8_TSQLTextNormalizer\8_TSQLTextNormalizer.csproj", "{D131443D-20C2-40F2-9D8B-6DA0EBE763B7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "9_TSQLRewrite", "9_TSQLRewrite\9_TSQLRewrite.csproj", "{303F7887-FC8F-4237-AE88-39F81AF9274E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {88301D6F-7C0B-4950-891D-999F991133A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {88301D6F-7C0B-4950-891D-999F991133A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {88301D6F-7C0B-4950-891D-999F991133A6}.Debug|x64.ActiveCfg = Debug|Any CPU + {88301D6F-7C0B-4950-891D-999F991133A6}.Debug|x64.Build.0 = Debug|Any CPU {88301D6F-7C0B-4950-891D-999F991133A6}.Debug|x86.ActiveCfg = Debug|x86 {88301D6F-7C0B-4950-891D-999F991133A6}.Debug|x86.Build.0 = Debug|x86 + {88301D6F-7C0B-4950-891D-999F991133A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {88301D6F-7C0B-4950-891D-999F991133A6}.Release|Any CPU.Build.0 = Release|Any CPU + {88301D6F-7C0B-4950-891D-999F991133A6}.Release|x64.ActiveCfg = Release|Any CPU + {88301D6F-7C0B-4950-891D-999F991133A6}.Release|x64.Build.0 = Release|Any CPU {88301D6F-7C0B-4950-891D-999F991133A6}.Release|x86.ActiveCfg = Release|x86 {88301D6F-7C0B-4950-891D-999F991133A6}.Release|x86.Build.0 = Release|x86 + {46DADD69-CF9A-410D-805C-A24A8000327C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46DADD69-CF9A-410D-805C-A24A8000327C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46DADD69-CF9A-410D-805C-A24A8000327C}.Debug|x64.ActiveCfg = Debug|Any CPU + {46DADD69-CF9A-410D-805C-A24A8000327C}.Debug|x64.Build.0 = Debug|Any CPU {46DADD69-CF9A-410D-805C-A24A8000327C}.Debug|x86.ActiveCfg = Debug|x86 {46DADD69-CF9A-410D-805C-A24A8000327C}.Debug|x86.Build.0 = Debug|x86 + {46DADD69-CF9A-410D-805C-A24A8000327C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46DADD69-CF9A-410D-805C-A24A8000327C}.Release|Any CPU.Build.0 = Release|Any CPU + {46DADD69-CF9A-410D-805C-A24A8000327C}.Release|x64.ActiveCfg = Release|Any CPU + {46DADD69-CF9A-410D-805C-A24A8000327C}.Release|x64.Build.0 = Release|Any CPU {46DADD69-CF9A-410D-805C-A24A8000327C}.Release|x86.ActiveCfg = Release|x86 {46DADD69-CF9A-410D-805C-A24A8000327C}.Release|x86.Build.0 = Release|x86 + {3C51886E-96B8-4037-8D69-DED60EE1D557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C51886E-96B8-4037-8D69-DED60EE1D557}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C51886E-96B8-4037-8D69-DED60EE1D557}.Debug|x64.ActiveCfg = Debug|Any CPU + {3C51886E-96B8-4037-8D69-DED60EE1D557}.Debug|x64.Build.0 = Debug|Any CPU {3C51886E-96B8-4037-8D69-DED60EE1D557}.Debug|x86.ActiveCfg = Debug|x86 {3C51886E-96B8-4037-8D69-DED60EE1D557}.Debug|x86.Build.0 = Debug|x86 + {3C51886E-96B8-4037-8D69-DED60EE1D557}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C51886E-96B8-4037-8D69-DED60EE1D557}.Release|Any CPU.Build.0 = Release|Any CPU + {3C51886E-96B8-4037-8D69-DED60EE1D557}.Release|x64.ActiveCfg = Release|Any CPU + {3C51886E-96B8-4037-8D69-DED60EE1D557}.Release|x64.Build.0 = Release|Any CPU {3C51886E-96B8-4037-8D69-DED60EE1D557}.Release|x86.ActiveCfg = Release|x86 {3C51886E-96B8-4037-8D69-DED60EE1D557}.Release|x86.Build.0 = Release|x86 + {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Debug|x64.ActiveCfg = Debug|Any CPU + {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Debug|x64.Build.0 = Debug|Any CPU {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Debug|x86.ActiveCfg = Debug|x86 {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Debug|x86.Build.0 = Debug|x86 + {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Release|Any CPU.Build.0 = Release|Any CPU + {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Release|x64.ActiveCfg = Release|Any CPU + {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Release|x64.Build.0 = Release|Any CPU {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Release|x86.ActiveCfg = Release|x86 {34808131-3AA3-4D50-A2C0-B47F93651A6E}.Release|x86.Build.0 = Release|x86 + {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Debug|x64.ActiveCfg = Debug|Any CPU + {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Debug|x64.Build.0 = Debug|Any CPU {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Debug|x86.ActiveCfg = Debug|x86 {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Debug|x86.Build.0 = Debug|x86 + {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Release|Any CPU.Build.0 = Release|Any CPU + {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Release|x64.ActiveCfg = Release|Any CPU + {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Release|x64.Build.0 = Release|Any CPU {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Release|x86.ActiveCfg = Release|x86 {D45AB243-99C3-4DD0-B692-835D3BF4E0C0}.Release|x86.Build.0 = Release|x86 + {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Debug|x64.ActiveCfg = Debug|Any CPU + {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Debug|x64.Build.0 = Debug|Any CPU {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Debug|x86.ActiveCfg = Debug|x86 {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Debug|x86.Build.0 = Debug|x86 + {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Release|Any CPU.Build.0 = Release|Any CPU + {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Release|x64.ActiveCfg = Release|Any CPU + {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Release|x64.Build.0 = Release|Any CPU {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Release|x86.ActiveCfg = Release|x86 {51E8719C-0ACA-4C79-AE31-7DE0DC0D5BE7}.Release|x86.Build.0 = Release|x86 + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Debug|x64.ActiveCfg = Debug|Any CPU + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Debug|x64.Build.0 = Debug|Any CPU + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Debug|x86.ActiveCfg = Debug|x86 + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Debug|x86.Build.0 = Debug|x86 + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Release|Any CPU.Build.0 = Release|Any CPU + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Release|x64.ActiveCfg = Release|Any CPU + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Release|x64.Build.0 = Release|Any CPU + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Release|x86.ActiveCfg = Release|x86 + {82E6E27C-2B4D-4D83-A797-18EBF1F721F2}.Release|x86.Build.0 = Release|x86 + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Debug|x64.ActiveCfg = Debug|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Debug|x64.Build.0 = Debug|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Debug|x86.ActiveCfg = Debug|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Debug|x86.Build.0 = Debug|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Release|Any CPU.Build.0 = Release|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Release|x64.ActiveCfg = Release|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Release|x64.Build.0 = Release|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Release|x86.ActiveCfg = Release|Any CPU + {D131443D-20C2-40F2-9D8B-6DA0EBE763B7}.Release|x86.Build.0 = Release|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Debug|x64.ActiveCfg = Debug|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Debug|x64.Build.0 = Debug|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Debug|x86.ActiveCfg = Debug|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Debug|x86.Build.0 = Debug|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Release|Any CPU.Build.0 = Release|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Release|x64.ActiveCfg = Release|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Release|x64.Build.0 = Release|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Release|x86.ActiveCfg = Release|Any CPU + {303F7887-FC8F-4237-AE88-39F81AF9274E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {698BF626-CEC2-4FAF-80A3-40D515134A54} = {A19B07A2-A103-4BC5-9705-F8C01FCE3C5D} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {939348C3-B244-4160-B9C0-66DFE32ED9B2} + EndGlobalSection EndGlobal