From 1363fa329f15bce85eac09e3ec8f075cb7fe57d3 Mon Sep 17 00:00:00 2001 From: Jeremy Morton Date: Sat, 18 Feb 2023 14:32:36 +0000 Subject: [PATCH 1/2] Allow custom DB creation script to be passed. --- .../NoPublicApiChanges.Run.approved.cs | 21 +-- src/dbup-sqlserver/SqlServerExtensions.cs | 139 +++++++++++------- 2 files changed, 98 insertions(+), 62 deletions(-) diff --git a/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs b/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs index 5c750d7..11b0244 100644 --- a/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs +++ b/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs @@ -1,4 +1,4 @@ -[assembly: System.CLSCompliantAttribute(false)] +[assembly: System.CLSCompliantAttribute(false)] [assembly: System.Runtime.InteropServices.ComVisibleAttribute(false)] [assembly: System.Runtime.InteropServices.GuidAttribute("8190b40b-ac5b-414f-8a00-9b6a2c12b010")] @@ -9,23 +9,24 @@ public static DbUp.Builder.UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSe public static class SqlServerExtensions { public static DbUp.Builder.UpgradeEngineBuilder JournalToSqlTable(this DbUp.Builder.UpgradeEngineBuilder builder, string schema, string table) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, string collation) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, string collation) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition, string collation) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition, string collation) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout = -1, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition = 0, string collation = null, System.Collections.Generic.IList createDbSqlCommands = null, bool checkOnly = false) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.Engine.Output.IUpgradeLog logger, int timeout = -1, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition = 0, string collation = null, System.Collections.Generic.IList createDbSqlCommands = null, bool checkOnly = false) { } public static DbUp.Builder.UpgradeEngineBuilder SqlDatabase(this DbUp.Builder.SupportedDatabases supported, string connectionString) { } public static DbUp.Builder.UpgradeEngineBuilder SqlDatabase(this DbUp.Builder.SupportedDatabases supported, string connectionString, string schema) { } public static DbUp.Builder.UpgradeEngineBuilder SqlDatabase(this DbUp.Builder.SupportedDatabases supported, DbUp.Engine.Transactions.IConnectionManager connectionManager, string schema = null) { } [System.ObsoleteAttribute("Use "AzureSqlDatabaseWithIntegratedSecurity(this SupportedDatabases, string, string)" if passing "true" to "useAzureSqlIntegratedSecurity".")] public static DbUp.Builder.UpgradeEngineBuilder SqlDatabase(this DbUp.Builder.SupportedDatabases supported, string connectionString, string schema, bool useAzureSqlIntegratedSecurity) { } - public static void SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString) { } public static void SqlDatabase(this DbUp.SupportedDatabasesForDropDatabase supported, string connectionString) { } - public static void SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition) { } - public static void SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout) { } - public static void SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, string collation) { } public static void SqlDatabase(this DbUp.SupportedDatabasesForDropDatabase supported, string connectionString, int commandTimeout) { } - public static void SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition) { } - public static void SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, string collation) { } - public static void SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition, string collation) { } public static void SqlDatabase(this DbUp.SupportedDatabasesForDropDatabase supported, string connectionString, DbUp.Engine.Output.IUpgradeLog logger, int timeout = -1) { } - public static void SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition, string collation) { } - public static void SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.Engine.Output.IUpgradeLog logger, int timeout = -1, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition = 0, string collation = null) { } } namespace DbUp.SqlServer { diff --git a/src/dbup-sqlserver/SqlServerExtensions.cs b/src/dbup-sqlserver/SqlServerExtensions.cs index a0268c6..4117b34 100644 --- a/src/dbup-sqlserver/SqlServerExtensions.cs +++ b/src/dbup-sqlserver/SqlServerExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Data; using Microsoft.Data.SqlClient; using DbUp; @@ -110,10 +111,10 @@ public static UpgradeEngineBuilder JournalToSqlTable(this UpgradeEngineBuilder b /// /// Fluent helper type. /// The connection string. - /// - public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString) + /// True if the database was (or would've been) created; otherwise false. + public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString) { - SqlDatabase(supported, connectionString, new ConsoleUpgradeLog()); + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog()); } /// @@ -122,10 +123,10 @@ public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supporte /// Fluent helper type. /// The connection string. /// Azure edition to Create - /// - public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, AzureDatabaseEdition azureDatabaseEdition) + /// True if the database was (or would've been) created; otherwise false. + public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, AzureDatabaseEdition azureDatabaseEdition) { - SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), -1, azureDatabaseEdition); + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), -1, azureDatabaseEdition); } /// @@ -134,10 +135,10 @@ public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supporte /// Fluent helper type. /// The connection string. /// Use this to set the command time out for creating a database in case you're encountering a time out in this operation. - /// - public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout) + /// True if the database was (or would've been) created; otherwise false. + public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout) { - SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout); + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout); } /// @@ -146,10 +147,10 @@ public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supporte /// Fluent helper type. /// The connection string. /// The collation name to set during database creation - /// - public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, string collation) + /// True if the database was (or would've been) created; otherwise false. + public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, string collation) { - SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), collation: collation); + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), collation: collation); } /// @@ -159,10 +160,10 @@ public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supporte /// The connection string. /// Use this to set the command time out for creating a database in case you're encountering a time out in this operation. /// Azure edition to Create - /// - public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, AzureDatabaseEdition azureDatabaseEdition) + /// True if the database was (or would've been) created; otherwise false. + public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, AzureDatabaseEdition azureDatabaseEdition) { - SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, azureDatabaseEdition); + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, azureDatabaseEdition); } /// @@ -172,10 +173,10 @@ public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supporte /// The connection string. /// Use this to set the command time out for creating a database in case you're encountering a time out in this operation. /// The collation name to set during database creation - /// - public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, string collation) + /// True if the database was (or would've been) created; otherwise false. + public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, string collation) { - SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, collation: collation); + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, collation: collation); } /// @@ -185,10 +186,10 @@ public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supporte /// The connection string. /// Azure edition to Create /// The collation name to set during database creation - /// - public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, AzureDatabaseEdition azureDatabaseEdition, string collation) + /// True if the database was (or would've been) created; otherwise false. + public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, AzureDatabaseEdition azureDatabaseEdition, string collation) { - SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), azureDatabaseEdition: azureDatabaseEdition, collation: collation); + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), azureDatabaseEdition: azureDatabaseEdition, collation: collation); } /// @@ -199,10 +200,26 @@ public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supporte /// Use this to set the command time out for creating a database in case you're encountering a time out in this operation. /// Azure edition to Create /// The collation name to set during database creation - /// - public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, AzureDatabaseEdition azureDatabaseEdition, string collation) + /// True if the database was (or would've been) created; otherwise false. + public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, AzureDatabaseEdition azureDatabaseEdition, string collation) { - SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, azureDatabaseEdition, collation); + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, azureDatabaseEdition, collation); + } + + /// + /// Ensures that the database specified in the connection string exists. + /// + /// Fluent helper type. + /// The connection string. + /// Use this to set the command time out for creating a database in case you're encountering a time out in this operation. + /// Azure edition to Create + /// The collation name to set during database creation + /// A list of custom SQL commands that will be used to create the database. + /// If true, only checks whether the database would've been created but does not perform the creation. + /// True if the database was (or would've been) created; otherwise false. + public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout = -1, AzureDatabaseEdition azureDatabaseEdition = AzureDatabaseEdition.None, string collation = null, IList createDbSqlCommands = null, bool checkOnly = false) + { + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, azureDatabaseEdition, collation, createDbSqlCommands, checkOnly); } /// @@ -214,14 +231,18 @@ public static void SqlDatabase(this SupportedDatabasesForEnsureDatabase supporte /// Use this to set the command time out for creating a database in case you're encountering a time out in this operation. /// Use to indicate that the SQL server database is in Azure /// The collation name to set during database creation - /// - public static void SqlDatabase( + /// A list of custom SQL commands that will be used to create the database. + /// If true, only checks whether the database would've been created but does not perform the creation. + /// True if the database was (or would've been) created; otherwise false. + public static bool SqlDatabase( this SupportedDatabasesForEnsureDatabase supported, string connectionString, IUpgradeLog logger, int timeout = -1, AzureDatabaseEdition azureDatabaseEdition = AzureDatabaseEdition.None, - string collation = null) + string collation = null, + IList createDbSqlCommands = null, + bool checkOnly = false) { GetMasterConnectionStringBuilder(connectionString, logger, out var masterConnectionString, out var databaseName); @@ -235,48 +256,62 @@ public static void SqlDatabase( { // Failed to connect to master, lets try direct if (DatabaseExistsIfConnectedToDirectly(logger, connectionString, databaseName)) - return; + return false; throw; } if (DatabaseExists(connection, databaseName)) - return; + return false; - var collationString = string.IsNullOrEmpty(collation) ? "" : $@" COLLATE {collation}"; - var sqlCommandText = $@"create database [{databaseName}]{collationString}"; + if (checkOnly) + return true; - switch (azureDatabaseEdition) + if (createDbSqlCommands == null) { - case AzureDatabaseEdition.None: - sqlCommandText += ";"; - break; - case AzureDatabaseEdition.Basic: - sqlCommandText += " ( EDITION = ''basic'' );"; - break; - case AzureDatabaseEdition.Standard: - sqlCommandText += " ( EDITION = ''standard'' );"; - break; - case AzureDatabaseEdition.Premium: - sqlCommandText += " ( EDITION = ''premium'' );"; - break; + createDbSqlCommands = new List(); + var collationString = string.IsNullOrEmpty(collation) ? "" : $@" COLLATE {collation}"; + var sqlCommandText = $@"create database [{databaseName}]{collationString}"; + + switch (azureDatabaseEdition) + { + case AzureDatabaseEdition.None: + sqlCommandText += ";"; + break; + case AzureDatabaseEdition.Basic: + sqlCommandText += " ( EDITION = ''basic'' );"; + break; + case AzureDatabaseEdition.Standard: + sqlCommandText += " ( EDITION = ''standard'' );"; + break; + case AzureDatabaseEdition.Premium: + sqlCommandText += " ( EDITION = ''premium'' );"; + break; + } + + createDbSqlCommands.Add(sqlCommandText); } // Create the database... - using (var command = new SqlCommand(sqlCommandText, connection) + foreach (var sqlCommandText in createDbSqlCommands) { - CommandType = CommandType.Text - }) - { - if (timeout >= 0) + using (var command = new SqlCommand(sqlCommandText, connection) { - command.CommandTimeout = timeout; - } + CommandType = CommandType.Text + }) + { + if (timeout >= 0) + { + command.CommandTimeout = timeout; + } - command.ExecuteNonQuery(); + command.ExecuteNonQuery(); + } } logger.LogInformation(@"Created database {0}", databaseName); + + return true; } } From c78397f24eae71bf1a557e845772b9cd1afa1c9f Mon Sep 17 00:00:00 2001 From: Jeremy Morton Date: Sat, 18 Feb 2023 14:54:35 +0000 Subject: [PATCH 2/2] Use factory to generate DB creation script instead. # Conflicts: # src/dbup-tests/Support/SqlServer/ApprovalFiles/dbup-sqlserver.netfx.approved.cs --- .../NoPublicApiChanges.Run.approved.cs | 4 ++-- src/dbup-sqlserver/SqlServerExtensions.cs | 17 +++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs b/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs index 11b0244..c0b0bcb 100644 --- a/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs +++ b/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs @@ -17,8 +17,8 @@ public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase sup public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, string collation) { } public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition, string collation) { } public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition, string collation) { } - public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout = -1, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition = 0, string collation = null, System.Collections.Generic.IList createDbSqlCommands = null, bool checkOnly = false) { } - public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.Engine.Output.IUpgradeLog logger, int timeout = -1, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition = 0, string collation = null, System.Collections.Generic.IList createDbSqlCommands = null, bool checkOnly = false) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout = -1, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition = 0, string collation = null, System.Func> createDbSqlCommandsFactory = null, bool checkOnly = false) { } + public static bool SqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.Engine.Output.IUpgradeLog logger, int timeout = -1, DbUp.SqlServer.AzureDatabaseEdition azureDatabaseEdition = 0, string collation = null, System.Func> createDbSqlCommandsFactory = null, bool checkOnly = false) { } public static DbUp.Builder.UpgradeEngineBuilder SqlDatabase(this DbUp.Builder.SupportedDatabases supported, string connectionString) { } public static DbUp.Builder.UpgradeEngineBuilder SqlDatabase(this DbUp.Builder.SupportedDatabases supported, string connectionString, string schema) { } public static DbUp.Builder.UpgradeEngineBuilder SqlDatabase(this DbUp.Builder.SupportedDatabases supported, DbUp.Engine.Transactions.IConnectionManager connectionManager, string schema = null) { } diff --git a/src/dbup-sqlserver/SqlServerExtensions.cs b/src/dbup-sqlserver/SqlServerExtensions.cs index 4117b34..528c97a 100644 --- a/src/dbup-sqlserver/SqlServerExtensions.cs +++ b/src/dbup-sqlserver/SqlServerExtensions.cs @@ -214,12 +214,12 @@ public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supporte /// Use this to set the command time out for creating a database in case you're encountering a time out in this operation. /// Azure edition to Create /// The collation name to set during database creation - /// A list of custom SQL commands that will be used to create the database. + /// A factory receiving the DB name, and returning a list of custom SQL commands that will be used to create the database. /// If true, only checks whether the database would've been created but does not perform the creation. /// True if the database was (or would've been) created; otherwise false. - public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout = -1, AzureDatabaseEdition azureDatabaseEdition = AzureDatabaseEdition.None, string collation = null, IList createDbSqlCommands = null, bool checkOnly = false) + public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, int commandTimeout = -1, AzureDatabaseEdition azureDatabaseEdition = AzureDatabaseEdition.None, string collation = null, Func> createDbSqlCommandsFactory = null, bool checkOnly = false) { - return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, azureDatabaseEdition, collation, createDbSqlCommands, checkOnly); + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, azureDatabaseEdition, collation, createDbSqlCommandsFactory, checkOnly); } /// @@ -231,7 +231,7 @@ public static bool SqlDatabase(this SupportedDatabasesForEnsureDatabase supporte /// Use this to set the command time out for creating a database in case you're encountering a time out in this operation. /// Use to indicate that the SQL server database is in Azure /// The collation name to set during database creation - /// A list of custom SQL commands that will be used to create the database. + /// A factory receiving the DB name, and returning a list of custom SQL commands that will be used to create the database. /// If true, only checks whether the database would've been created but does not perform the creation. /// True if the database was (or would've been) created; otherwise false. public static bool SqlDatabase( @@ -241,7 +241,7 @@ public static bool SqlDatabase( int timeout = -1, AzureDatabaseEdition azureDatabaseEdition = AzureDatabaseEdition.None, string collation = null, - IList createDbSqlCommands = null, + Func> createDbSqlCommandsFactory = null, bool checkOnly = false) { GetMasterConnectionStringBuilder(connectionString, logger, out var masterConnectionString, out var databaseName); @@ -267,7 +267,8 @@ public static bool SqlDatabase( if (checkOnly) return true; - if (createDbSqlCommands == null) + IList createDbSqlCommands; + if (createDbSqlCommandsFactory == null) { createDbSqlCommands = new List(); var collationString = string.IsNullOrEmpty(collation) ? "" : $@" COLLATE {collation}"; @@ -291,6 +292,10 @@ public static bool SqlDatabase( createDbSqlCommands.Add(sqlCommandText); } + else + { + createDbSqlCommands = createDbSqlCommandsFactory(databaseName); + } // Create the database... foreach (var sqlCommandText in createDbSqlCommands)