// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. namespace WixToolset.Sql { #if TODO_CONSIDER_DECOMPILER using System.Collections; using WixToolset.Data; using WixToolset.Extensibility; using Sql = WixToolset.Extensions.Serialize.Sql; using Wix = WixToolset.Data.Serialize; /// /// The decompiler for the WiX Toolset SQL Server Extension. /// public sealed class SqlDecompiler : DecompilerExtension { /// /// Creates a decompiler for SQL Extension. /// public SqlDecompiler() { this.TableDefinitions = SqlExtensionData.GetExtensionTableDefinitions(); } /// /// Get the extensions library to be removed. /// /// Table definitions for library. /// Library to remove from decompiled output. public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions) { return SqlExtensionData.GetExtensionLibrary(tableDefinitions); } /// /// Decompiles an extension table. /// /// The table to decompile. public override void DecompileTable(Table table) { switch (table.Name) { case "SqlDatabase": this.DecompileSqlDatabaseTable(table); break; case "SqlFileSpec": // handled in FinalizeSqlFileSpecTable break; case "SqlScript": this.DecompileSqlScriptTable(table); break; case "SqlString": this.DecompileSqlStringTable(table); break; default: base.DecompileTable(table); break; } } /// /// Finalize decompilation. /// /// The collection of all tables. public override void Finish(TableIndexedCollection tables) { this.FinalizeSqlFileSpecTable(tables); this.FinalizeSqlScriptAndSqlStringTables(tables); } /// /// Decompile the SqlDatabase table. /// /// The table to decompile. private void DecompileSqlDatabaseTable(Table table) { foreach (Row row in table.Rows) { Sql.SqlDatabase sqlDatabase = new Sql.SqlDatabase(); sqlDatabase.Id = (string)row[0]; if (null != row[1]) { sqlDatabase.Server = (string)row[1]; } if (null != row[2]) { sqlDatabase.Instance = (string)row[2]; } sqlDatabase.Database = (string)row[3]; if (null != row[5]) { sqlDatabase.User = (string)row[5]; } // the FileSpec_ and FileSpec_Log columns will be handled in FinalizeSqlFileSpecTable if (null != row[8]) { int attributes = (int)row[8]; if (SqlCompiler.DbCreateOnInstall == (attributes & SqlCompiler.DbCreateOnInstall)) { sqlDatabase.CreateOnInstall = Sql.YesNoType.yes; } if (SqlCompiler.DbDropOnUninstall == (attributes & SqlCompiler.DbDropOnUninstall)) { sqlDatabase.DropOnUninstall = Sql.YesNoType.yes; } if (SqlCompiler.DbContinueOnError == (attributes & SqlCompiler.DbContinueOnError)) { sqlDatabase.ContinueOnError = Sql.YesNoType.yes; } if (SqlCompiler.DbDropOnInstall == (attributes & SqlCompiler.DbDropOnInstall)) { sqlDatabase.DropOnInstall = Sql.YesNoType.yes; } if (SqlCompiler.DbCreateOnUninstall == (attributes & SqlCompiler.DbCreateOnUninstall)) { sqlDatabase.CreateOnUninstall = Sql.YesNoType.yes; } if (SqlCompiler.DbConfirmOverwrite == (attributes & SqlCompiler.DbConfirmOverwrite)) { sqlDatabase.ConfirmOverwrite = Sql.YesNoType.yes; } if (SqlCompiler.DbCreateOnReinstall == (attributes & SqlCompiler.DbCreateOnReinstall)) { sqlDatabase.CreateOnReinstall = Sql.YesNoType.yes; } if (SqlCompiler.DbDropOnReinstall == (attributes & SqlCompiler.DbDropOnReinstall)) { sqlDatabase.DropOnReinstall = Sql.YesNoType.yes; } } if (null != row[4]) { Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[4]); if (null != component) { component.AddChild(sqlDatabase); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[4], "Component")); } } else { this.Core.RootElement.AddChild(sqlDatabase); } this.Core.IndexElement(row, sqlDatabase); } } /// /// Decompile the SqlScript table. /// /// The table to decompile. private void DecompileSqlScriptTable(Table table) { foreach (Row row in table.Rows) { Sql.SqlScript sqlScript = new Sql.SqlScript(); sqlScript.Id = (string)row[0]; // the Db_ and Component_ columns are handled in FinalizeSqlScriptAndSqlStringTables sqlScript.BinaryKey = (string)row[3]; if (null != row[4]) { sqlScript.User = (string)row[4]; } int attributes = (int)row[5]; if (SqlCompiler.SqlContinueOnError == (attributes & SqlCompiler.SqlContinueOnError)) { sqlScript.ContinueOnError = Sql.YesNoType.yes; } if (SqlCompiler.SqlExecuteOnInstall == (attributes & SqlCompiler.SqlExecuteOnInstall)) { sqlScript.ExecuteOnInstall = Sql.YesNoType.yes; } if (SqlCompiler.SqlExecuteOnReinstall == (attributes & SqlCompiler.SqlExecuteOnReinstall)) { sqlScript.ExecuteOnReinstall = Sql.YesNoType.yes; } if (SqlCompiler.SqlExecuteOnUninstall == (attributes & SqlCompiler.SqlExecuteOnUninstall)) { sqlScript.ExecuteOnUninstall = Sql.YesNoType.yes; } if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall))) { sqlScript.RollbackOnInstall = Sql.YesNoType.yes; } if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall))) { sqlScript.RollbackOnReinstall = Sql.YesNoType.yes; } if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall))) { sqlScript.RollbackOnUninstall = Sql.YesNoType.yes; } if (null != row[6]) { sqlScript.Sequence = (int)row[6]; } this.Core.IndexElement(row, sqlScript); } } /// /// Decompile the SqlString table. /// /// The table to decompile. private void DecompileSqlStringTable(Table table) { foreach (Row row in table.Rows) { Sql.SqlString sqlString = new Sql.SqlString(); sqlString.Id = (string)row[0]; // the Db_ and Component_ columns are handled in FinalizeSqlScriptAndSqlStringTables sqlString.SQL = (string)row[3]; if (null != row[4]) { sqlString.User = (string)row[4]; } int attributes = (int)row[5]; if (SqlCompiler.SqlContinueOnError == (attributes & SqlCompiler.SqlContinueOnError)) { sqlString.ContinueOnError = Sql.YesNoType.yes; } if (SqlCompiler.SqlExecuteOnInstall == (attributes & SqlCompiler.SqlExecuteOnInstall)) { sqlString.ExecuteOnInstall = Sql.YesNoType.yes; } if (SqlCompiler.SqlExecuteOnReinstall == (attributes & SqlCompiler.SqlExecuteOnReinstall)) { sqlString.ExecuteOnReinstall = Sql.YesNoType.yes; } if (SqlCompiler.SqlExecuteOnUninstall == (attributes & SqlCompiler.SqlExecuteOnUninstall)) { sqlString.ExecuteOnUninstall = Sql.YesNoType.yes; } if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall))) { sqlString.RollbackOnInstall = Sql.YesNoType.yes; } if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall))) { sqlString.RollbackOnReinstall = Sql.YesNoType.yes; } if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall))) { sqlString.RollbackOnUninstall = Sql.YesNoType.yes; } if (null != row[6]) { sqlString.Sequence = (int)row[6]; } this.Core.IndexElement(row, sqlString); } } /// /// Finalize the SqlFileSpec table. /// /// The collection of all tables. /// /// Since rows of the SqlFileSpec table are represented by either /// the SqlFileSpec or SqlLogFileSpec depending upon the context in /// which they are used in the SqlDatabase table, decompilation of this /// table must occur after the SqlDatbase parents are decompiled. /// private void FinalizeSqlFileSpecTable(TableIndexedCollection tables) { Table sqlDatabaseTable = tables["SqlDatabase"]; Table sqlFileSpecTable = tables["SqlFileSpec"]; if (null != sqlDatabaseTable && null != sqlFileSpecTable) { Hashtable sqlFileSpecRows = new Hashtable(); // index each SqlFileSpec row by its primary key foreach (Row row in sqlFileSpecTable.Rows) { sqlFileSpecRows.Add(row[0], row); } // create the necessary SqlFileSpec and SqlLogFileSpec elements for each row foreach (Row row in sqlDatabaseTable.Rows) { Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase)this.Core.GetIndexedElement(row); if (null != row[6]) { Row sqlFileSpecRow = (Row)sqlFileSpecRows[row[6]]; if (null != sqlFileSpecRow) { Sql.SqlFileSpec sqlFileSpec = new Sql.SqlFileSpec(); sqlFileSpec.Id = (string)sqlFileSpecRow[0]; if (null != sqlFileSpecRow[1]) { sqlFileSpec.Name = (string)sqlFileSpecRow[1]; } sqlFileSpec.Filename = (string)sqlFileSpecRow[2]; if (null != sqlFileSpecRow[3]) { sqlFileSpec.Size = (string)sqlFileSpecRow[3]; } if (null != sqlFileSpecRow[4]) { sqlFileSpec.MaxSize = (string)sqlFileSpecRow[4]; } if (null != sqlFileSpecRow[5]) { sqlFileSpec.GrowthSize = (string)sqlFileSpecRow[5]; } sqlDatabase.AddChild(sqlFileSpec); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlDatabaseTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileSpec_", (string)row[6], "SqlFileSpec")); } } if (null != row[7]) { Row sqlFileSpecRow = (Row)sqlFileSpecRows[row[7]]; if (null != sqlFileSpecRow) { Sql.SqlLogFileSpec sqlLogFileSpec = new Sql.SqlLogFileSpec(); sqlLogFileSpec.Id = (string)sqlFileSpecRow[0]; if (null != sqlFileSpecRow[1]) { sqlLogFileSpec.Name = (string)sqlFileSpecRow[1]; } sqlLogFileSpec.Filename = (string)sqlFileSpecRow[2]; if (null != sqlFileSpecRow[3]) { sqlLogFileSpec.Size = (string)sqlFileSpecRow[3]; } if (null != sqlFileSpecRow[4]) { sqlLogFileSpec.MaxSize = (string)sqlFileSpecRow[4]; } if (null != sqlFileSpecRow[5]) { sqlLogFileSpec.GrowthSize = (string)sqlFileSpecRow[5]; } sqlDatabase.AddChild(sqlLogFileSpec); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlDatabaseTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileSpec_Log", (string)row[7], "SqlFileSpec")); } } } } } /// /// Finalize the SqlScript table. /// /// The collection of all tables. /// /// The SqlScript and SqlString tables contain a foreign key into the SqlDatabase /// and Component tables. Depending upon the parent of the SqlDatabase /// element, the SqlScript and SqlString elements are nested under either the /// SqlDatabase or the Component element. /// private void FinalizeSqlScriptAndSqlStringTables(TableIndexedCollection tables) { Table sqlDatabaseTable = tables["SqlDatabase"]; Table sqlScriptTable = tables["SqlScript"]; Table sqlStringTable = tables["SqlString"]; Hashtable sqlDatabaseRows = new Hashtable(); // index each SqlDatabase row by its primary key if (null != sqlDatabaseTable) { foreach (Row row in sqlDatabaseTable.Rows) { sqlDatabaseRows.Add(row[0], row); } } if (null != sqlScriptTable) { foreach (Row row in sqlScriptTable.Rows) { Sql.SqlScript sqlScript = (Sql.SqlScript)this.Core.GetIndexedElement(row); Row sqlDatabaseRow = (Row)sqlDatabaseRows[row[1]]; string databaseComponent = (string)sqlDatabaseRow[4]; // determine if the SqlScript element should be nested under the database or another component if (null != databaseComponent && databaseComponent == (string)row[2]) { Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase)this.Core.GetIndexedElement(sqlDatabaseRow); sqlDatabase.AddChild(sqlScript); } else // nest under the component of the SqlDatabase row { Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); // set the Database value sqlScript.SqlDb = (string)row[1]; if (null != component) { component.AddChild(sqlScript); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlScriptTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); } } } } if (null != sqlStringTable) { foreach (Row row in sqlStringTable.Rows) { Sql.SqlString sqlString = (Sql.SqlString)this.Core.GetIndexedElement(row); Row sqlDatabaseRow = (Row)sqlDatabaseRows[row[1]]; string databaseComponent = (string)sqlDatabaseRow[4]; // determine if the SqlScript element should be nested under the database or another component if (null != databaseComponent && databaseComponent == (string)row[2]) { Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase)this.Core.GetIndexedElement(sqlDatabaseRow); sqlDatabase.AddChild(sqlString); } else // nest under the component of the SqlDatabase row { Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); // set the Database value sqlString.SqlDb = (string)row[1]; if (null != component) { component.AddChild(sqlString); } else { this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlStringTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); } } } } } } #endif }