diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f1a6bc8..26798d9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,84 +2,12 @@ name: CI on: push: + branches: + - '**' # Ignores pushes of tags pull_request: workflow_dispatch: jobs: build: - runs-on: windows-latest # Use Ubuntu in v5.0 - - env: - DOTNET_NOLOGO: true - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true # Avoid pre-populating the NuGet package cache - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 # all - - - name: Setup .NET 2.0 # Remove in v5.0 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 2.0.x - - - name: Setup .NET 8.0 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 8.0.x - - - name: Install NuGet - uses: NuGet/setup-nuget@v1.2.0 - - - name: Install GitVersion - uses: gittools/actions/gitversion/setup@v0 - with: - versionSpec: '5.x' - - - name: Run GitVersion - id: gitversion - uses: gittools/actions/gitversion/execute@v0 - - - name: Display SemVer - run: | - echo "SemVer: $env:GitVersion_SemVer" - - - name: Add DbUp NuGet Source - run: dotnet nuget add source --name DbUp --username DbUp --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text https://nuget.pkg.github.com/DbUp/index.json - - - name: Restore - run: dotnet restore - working-directory: src - - - name: Build - run: dotnet build -c Release --no-restore /p:Version=$env:GitVersion_SemVer - working-directory: src - - - name: Test - run: dotnet test --no-build -c Release --logger trx --logger "console;verbosity=detailed" --results-directory ../artifacts - working-directory: src - - - name: Pack - run: dotnet pack --no-build -c Release -o ../artifacts /p:Version=$env:GitVersion_SemVer - working-directory: src - - - name: Pack placeholder dbup package - run: nuget pack ./dbup/dbup.nuspec -OutputDirectory ../artifacts -Version $env:GitVersion_SemVer - working-directory: src - - - name: Push NuGet packages to GitHub Packages ⬆️ - working-directory: artifacts - run: dotnet nuget push *.nupkg --api-key ${{ secrets.GITHUB_TOKEN }} --source "https://nuget.pkg.github.com/DbUp/index.json" - - - name: Push NuGet packages to NuGet ⬆️ - if: ${{ steps.gitversion.outputs.preReleaseLabel == '' }} - working-directory: artifacts - run: dotnet nuget push *.nupkg --api-key ${{ secrets.NUGET_APIKEY }} --source https://api.nuget.org/v3/index.json - - - name: Test Report 🧪 - uses: dorny/test-reporter@v1 - if: ${{ always() }} - with: - name: Tests - path: artifacts/*.trx - reporter: dotnet-trx + name: Build + uses: DbUp/Universe/.github/workflows/build.yml@main diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml new file mode 100644 index 0000000..eb5e03f --- /dev/null +++ b/.github/workflows/publish-release.yml @@ -0,0 +1,12 @@ +name: Publish DbUp Packages to NuGet + +on: + release: + types: [ published ] + workflow_dispatch: + +jobs: + publish: + name: Publish Package + uses: DbUp/Universe/.github/workflows/publish-release.yml@main + secrets: inherit diff --git a/GitVersion.yml b/GitVersion.yml index c311488..9c1685d 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1 +1,2 @@ -mode: Mainline \ No newline at end of file +mode: Mainline +next-version: 6.0.0 \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 196f572..71548cd 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -11,17 +11,4 @@ true - - - - true - - - true - - - embedded - - - diff --git a/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyBasicSupport.verified.txt b/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyBasicSupport.approved.txt similarity index 90% rename from src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyBasicSupport.verified.txt rename to src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyBasicSupport.approved.txt index 6192175..4df7abb 100644 --- a/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyBasicSupport.verified.txt +++ b/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyBasicSupport.approved.txt @@ -1,11 +1,11 @@ -DB Operation: Open connection +DB Operation: Open connection Info: Beginning database upgrade -Info: Checking whether journal table exists.. +Info: Checking whether journal table exists DB Operation: Execute scalar command: select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'SchemaVersions' DB Operation: Dispose command Info: Journal table does not exist Info: Executing Database Server script 'Script0001.sql' -Info: Checking whether journal table exists.. +Info: Checking whether journal table exists DB Operation: Execute scalar command: select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'SchemaVersions' DB Operation: Dispose command Info: Creating the [SchemaVersions] table diff --git a/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyJournalCreationIfNameChanged.verified.txt b/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyJournalCreationIfNameChanged.approved.txt similarity index 91% rename from src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyJournalCreationIfNameChanged.verified.txt rename to src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyJournalCreationIfNameChanged.approved.txt index 9ca0e23..1f52d9c 100644 --- a/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyJournalCreationIfNameChanged.verified.txt +++ b/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyJournalCreationIfNameChanged.approved.txt @@ -1,11 +1,11 @@ -DB Operation: Open connection +DB Operation: Open connection Info: Beginning database upgrade -Info: Checking whether journal table exists.. +Info: Checking whether journal table exists DB Operation: Execute scalar command: select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'TestSchemaVersions' and TABLE_SCHEMA = 'test' DB Operation: Dispose command Info: Journal table does not exist Info: Executing Database Server script 'Script0001.sql' -Info: Checking whether journal table exists.. +Info: Checking whether journal table exists DB Operation: Execute scalar command: select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'TestSchemaVersions' and TABLE_SCHEMA = 'test' DB Operation: Dispose command Info: Creating the [test].[TestSchemaVersions] table diff --git a/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyVariableSubstitutions.verified.txt b/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyVariableSubstitutions.approved.txt similarity index 90% rename from src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyVariableSubstitutions.verified.txt rename to src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyVariableSubstitutions.approved.txt index 9c20bfc..c3fa619 100644 --- a/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyVariableSubstitutions.verified.txt +++ b/src/Tests/ApprovalFiles/DatabaseSupportTests.VerifyVariableSubstitutions.approved.txt @@ -1,11 +1,11 @@ -DB Operation: Open connection +DB Operation: Open connection Info: Beginning database upgrade -Info: Checking whether journal table exists.. +Info: Checking whether journal table exists DB Operation: Execute scalar command: select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'SchemaVersions' DB Operation: Dispose command Info: Journal table does not exist Info: Executing Database Server script 'Script0001.sql' -Info: Checking whether journal table exists.. +Info: Checking whether journal table exists DB Operation: Execute scalar command: select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'SchemaVersions' DB Operation: Dispose command Info: Creating the [SchemaVersions] table diff --git a/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.Net.verified.cs b/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.Net.verified.cs deleted file mode 100644 index 288c72f..0000000 --- a/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.Net.verified.cs +++ /dev/null @@ -1,86 +0,0 @@ -[assembly: System.CLSCompliantAttribute(true)] -[assembly: System.Runtime.InteropServices.ComVisibleAttribute(false)] -[assembly: System.Runtime.InteropServices.GuidAttribute("8190b40b-ac5b-414f-8a00-9b6a2c12b010")] - -public static class AzureSqlServerExtensions -{ - public static DbUp.Builder.UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity(this DbUp.Builder.SupportedDatabases supported, string connectionString, string schema) { } - public static DbUp.Builder.UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity(this DbUp.Builder.SupportedDatabases supported, string connectionString, string schema, string resource) { } - public static DbUp.Builder.UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity(this DbUp.Builder.SupportedDatabases supported, string connectionString, string schema, string resource, string tenantId, string azureAdInstance = "https://login.microsoftonline.com/") { } -} -public static class SqlServerExtensions -{ - public static DbUp.Builder.UpgradeEngineBuilder JournalToSqlTable(this DbUp.Builder.UpgradeEngineBuilder builder, string schema, string table) { } - public static DbUp.Builder.UpgradeEngineBuilder LogToSqlContext(this DbUp.Builder.UpgradeEngineBuilder builder) { } - 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 -{ - public enum AzureDatabaseEdition : int - { - None = 0 - Basic = 1 - Standard = 2 - Premium = 3 - } - public class AzureSqlConnectionManager : DbUp.Engine.Transactions.DatabaseConnectionManager, DbUp.Engine.Transactions.IConnectionManager - { - public AzureSqlConnectionManager(string connectionString) { } - public AzureSqlConnectionManager(string connectionString, string resource) { } - public AzureSqlConnectionManager(string connectionString, string resource, string tenantId, string azureAdInstance = "https://login.microsoftonline.com/") { } - public override System.Collections.Generic.IEnumerable SplitScriptIntoCommands(string scriptContents) { } - } - public class SqlConnectionManager : DbUp.Engine.Transactions.DatabaseConnectionManager, DbUp.Engine.Transactions.IConnectionManager - { - public SqlConnectionManager(string connectionString) { } - public override System.Collections.Generic.IEnumerable SplitScriptIntoCommands(string scriptContents) { } - } - public class SqlScriptExecutor : DbUp.Support.ScriptExecutor, DbUp.Engine.IScriptExecutor - { - public SqlScriptExecutor(System.Func connectionManagerFactory, System.Func log, string schema, System.Func variablesEnabled, System.Collections.Generic.IEnumerable scriptPreprocessors, System.Func journalFactory) { } - protected override void ExecuteCommandsWithinExceptionHandler(int index, DbUp.Engine.SqlScript script, System.Action executeCommand) { } - protected override string GetVerifySchemaSql(string schema) { } - } - public class SqlServerObjectParser : DbUp.Support.SqlObjectParser, DbUp.Engine.ISqlObjectParser - { - public SqlServerObjectParser() { } - public override string QuoteIdentifier(string objectName, DbUp.Support.ObjectNameOptions objectNameOptions) { } - } - public class SqlTableJournal : DbUp.Support.TableJournal, DbUp.Engine.IJournal - { - public SqlTableJournal(System.Func connectionManager, System.Func logger, string schema, string table) { } - protected override string CreateSchemaTableSql(string quotedPrimaryKeyName) { } - protected override string GetInsertJournalEntrySql(string scriptName, string applied) { } - protected override string GetJournalEntriesSql() { } - } -} -namespace DbUp.SqlServer.Helpers -{ - public class TemporarySqlDatabase : System.IDisposable - { - public TemporarySqlDatabase(string name) { } - public TemporarySqlDatabase(System.Data.SqlClient.SqlConnectionStringBuilder connectionStringBuilder) { } - public TemporarySqlDatabase(string name, string instanceName) { } - public DbUp.Helpers.AdHocSqlRunner AdHoc { get; } - public string ConnectionString { get; } - public void Create() { } - public void Dispose() { } - public static DbUp.SqlServer.Helpers.TemporarySqlDatabase FromConnectionString(string connectionString) { } - } -} diff --git a/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.DotNet.verified.cs b/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs similarity index 80% rename from src/Tests/ApprovalFiles/NoPublicApiChanges.Run.DotNet.verified.cs rename to src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs index 98376b6..c0b0bcb 100644 --- a/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.DotNet.verified.cs +++ b/src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs @@ -1,33 +1,32 @@ -[assembly: System.CLSCompliantAttribute(true)] +[assembly: System.CLSCompliantAttribute(false)] [assembly: System.Runtime.InteropServices.ComVisibleAttribute(false)] [assembly: System.Runtime.InteropServices.GuidAttribute("8190b40b-ac5b-414f-8a00-9b6a2c12b010")] public static class AzureSqlServerExtensions { - public static DbUp.Builder.UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity(this DbUp.Builder.SupportedDatabases supported, string connectionString, string schema) { } - public static DbUp.Builder.UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity(this DbUp.Builder.SupportedDatabases supported, string connectionString, string schema, string resource) { } - public static DbUp.Builder.UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity(this DbUp.Builder.SupportedDatabases supported, string connectionString, string schema, string resource, string tenantId, string azureAdInstance = "https://login.microsoftonline.com/") { } + public static DbUp.Builder.UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity(this DbUp.Builder.SupportedDatabases supported, string connectionString, string schema = null, Azure.Core.TokenCredential tokenCredential = null, string resource = "https://database.windows.net/", string tenantId = null) { } } 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.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) { } [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 { @@ -40,9 +39,7 @@ public enum AzureDatabaseEdition : int } public class AzureSqlConnectionManager : DbUp.Engine.Transactions.DatabaseConnectionManager, DbUp.Engine.Transactions.IConnectionManager { - public AzureSqlConnectionManager(string connectionString) { } - public AzureSqlConnectionManager(string connectionString, string resource) { } - public AzureSqlConnectionManager(string connectionString, string resource, string tenantId, string azureAdInstance = "https://login.microsoftonline.com/") { } + public AzureSqlConnectionManager(string connectionString, Azure.Core.TokenCredential tokenCredential, string resource = "https://database.windows.net/", string tenantId = null) { } public override System.Collections.Generic.IEnumerable SplitScriptIntoCommands(string scriptContents) { } } public class SqlConnectionManager : DbUp.Engine.Transactions.DatabaseConnectionManager, DbUp.Engine.Transactions.IConnectionManager diff --git a/src/Tests/SqlScriptExecutorTests.cs b/src/Tests/SqlScriptExecutorTests.cs index 9107103..21908e6 100644 --- a/src/Tests/SqlScriptExecutorTests.cs +++ b/src/Tests/SqlScriptExecutorTests.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Data; +using System.Data; using System.Data.Common; using DbUp.Engine; using DbUp.Engine.Output; @@ -18,7 +16,8 @@ public class SqlScriptExecutorTests [Fact] public void verify_schema_should_not_check_when_schema_is_null() { - var executor = new SqlScriptExecutor(() => Substitute.For(), () => null, null, () => false, null, () => Substitute.For()); + var executor = new SqlScriptExecutor(() => Substitute.For(), () => null, null, + () => false, null, () => Substitute.For()); executor.VerifySchema(); } @@ -26,10 +25,8 @@ public void verify_schema_should_not_check_when_schema_is_null() [Fact] public void when_schema_is_null_schema_is_stripped_from_scripts() { - var dbConnection = Substitute.For(); var command = Substitute.For(); - dbConnection.CreateCommand().Returns(command); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true), () => new ConsoleUpgradeLog(), null, () => true, null, () => Substitute.For()); + var executor = GetSqlScriptExecutor(command); executor.Execute(new SqlScript("Test", "create $schema$.Table")); @@ -40,12 +37,11 @@ public void when_schema_is_null_schema_is_stripped_from_scripts() [Fact] public void uses_variable_substitute_preprocessor_when_running_scripts() { - var dbConnection = Substitute.For(); var command = Substitute.For(); - dbConnection.CreateCommand().Returns(command); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true), () => new ConsoleUpgradeLog(), null, () => true, null, () => Substitute.For()); + var executor = GetSqlScriptExecutor(command); - executor.Execute(new SqlScript("Test", "create $foo$.Table"), new Dictionary { { "foo", "bar" } }); + executor.Execute(new SqlScript("Test", "create $foo$.Table"), + new Dictionary { { "foo", "bar" } }); command.Received().ExecuteNonQuery(); command.CommandText.ShouldBe("create bar.Table"); @@ -58,12 +54,11 @@ public void uses_variable_subtitute_preprocessor_when_running_scripts_with_singl create $foo$.Table"; var oneLineCommentResult = @"--from excel $A$6 create bar.Table"; - var dbConnection = Substitute.For(); - var command = Substitute.For(); - dbConnection.CreateCommand().Returns(command); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true), () => new ConsoleUpgradeLog(), null, () => true, null, () => Substitute.For()); - executor.Execute(new SqlScript("Test", oneLineComment), new Dictionary { { "foo", "bar" } }); + var command = Substitute.For(); + var executor = GetSqlScriptExecutor(command); + executor.Execute(new SqlScript("Test", oneLineComment), + new Dictionary { { "foo", "bar" } }); command.Received().ExecuteNonQuery(); command.CommandText.ShouldBe(oneLineCommentResult); @@ -76,12 +71,14 @@ public void uses_variable_substitute_preprocessor_when_running_scripts_with_one_ create $foo$.Table"; var oneLineCommentResult = @"/* from excel $A$6 */ create bar.Table"; - var dbConnection = Substitute.For(); + var command = Substitute.For(); - dbConnection.CreateCommand().Returns(command); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true), () => new ConsoleUpgradeLog(), null, () => true, null, () => Substitute.For()); + var executor = GetSqlScriptExecutor(command); + executor.Execute(new SqlScript("Test", oneLineComment), + new Dictionary { { "foo", "bar" } }); - executor.Execute(new SqlScript("Test", oneLineComment), new Dictionary { { "foo", "bar" } }); + executor.Execute(new SqlScript("Test", oneLineComment), + new Dictionary { { "foo", "bar" } }); command.Received().ExecuteNonQuery(); command.CommandText.ShouldBe(oneLineCommentResult); @@ -101,12 +98,13 @@ some comment from excel $A$6 some comment */ - create bar.Table"; var dbConnection = Substitute.For(); + create bar.Table"; + var dbConnection = Substitute.For(); var command = Substitute.For(); - dbConnection.CreateCommand().Returns(command); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true), () => new ConsoleUpgradeLog(), null, () => true, null, () => Substitute.For()); + var executor = GetSqlScriptExecutor(command); - executor.Execute(new SqlScript("Test", multiLineComment), new Dictionary { { "foo", "bar" } }); + executor.Execute(new SqlScript("Test", multiLineComment), + new Dictionary { { "foo", "bar" } }); command.Received().ExecuteNonQuery(); command.CommandText.ShouldBe(multiLineCommentResult); @@ -126,12 +124,13 @@ some comment --from excel $A$6 some comment */ - create bar.Table"; var dbConnection = Substitute.For(); + create bar.Table"; + var dbConnection = Substitute.For(); var command = Substitute.For(); - dbConnection.CreateCommand().Returns(command); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true), () => new ConsoleUpgradeLog(), null, () => true, null, () => Substitute.For()); + var executor = GetSqlScriptExecutor(command); - executor.Execute(new SqlScript("Test", multiLineComment), new Dictionary { { "foo", "bar" } }); + executor.Execute(new SqlScript("Test", multiLineComment), + new Dictionary { { "foo", "bar" } }); command.Received().ExecuteNonQuery(); command.CommandText.ShouldBe(multiLineCommentResult); @@ -151,12 +150,13 @@ some comment /* from excel $A$6 */ some comment */ - create bar.Table"; var dbConnection = Substitute.For(); + create bar.Table"; + var dbConnection = Substitute.For(); var command = Substitute.For(); - dbConnection.CreateCommand().Returns(command); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true), () => new ConsoleUpgradeLog(), null, () => true, null, () => Substitute.For()); + var executor = GetSqlScriptExecutor(command); - executor.Execute(new SqlScript("Test", multiLineComment), new Dictionary { { "foo", "bar" } }); + executor.Execute(new SqlScript("Test", multiLineComment), + new Dictionary { { "foo", "bar" } }); command.Received().ExecuteNonQuery(); command.CommandText.ShouldBe(multiLineCommentResult); @@ -165,24 +165,22 @@ some comment [Fact] public void does_not_use_variable_substitute_preprocessor_when_setting_false() { - var dbConnection = Substitute.For(); var command = Substitute.For(); - dbConnection.CreateCommand().Returns(command); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true), () => new ConsoleUpgradeLog(), null, () => false, null, () => Substitute.For()); + var executor = GetSqlScriptExecutor(command, variablesEnabled: false); - executor.Execute(new SqlScript("Test", "create $foo$.Table"), new Dictionary { { "foo", "bar" } }); + executor.Execute(new SqlScript("Test", "create $foo$.Table"), + new Dictionary { { "foo", "bar" } }); command.Received().ExecuteNonQuery(); command.CommandText.ShouldBe("create $foo$.Table"); } + [Fact] public void uses_variable_subtitutes_schema() { - var dbConnection = Substitute.For(); var command = Substitute.For(); - dbConnection.CreateCommand().Returns(command); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true), () => new ConsoleUpgradeLog(), "foo", () => true, null, () => Substitute.For()); + var executor = GetSqlScriptExecutor(command, schema: "foo"); executor.Execute(new SqlScript("Test", "create $schema$.Table")); @@ -193,7 +191,6 @@ public void uses_variable_subtitutes_schema() [Fact] public void logs_output_when_configured_to() { - var dbConnection = Substitute.For(); var command = Substitute.For(); var reader = Substitute.For(); @@ -210,31 +207,22 @@ public void logs_output_when_configured_to() command.ExecuteReader().Returns(reader); var logger = new CaptureLogsLogger(); - dbConnection.CreateCommand().Returns(command); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true) { IsScriptOutputLogged = true }, - () => logger, - "foo", - () => true, - null, - () => Substitute.For()); + var executor = GetSqlScriptExecutor(command, log: logger, schema: "foo", isScriptOutputLogged: true); executor.Execute(new SqlScript("Test", "SELECT * FROM $schema$.[Table]")); - command.Received().ExecuteReader(); + command.ReceivedWithAnyArgs().ExecuteReader(); command.DidNotReceive().ExecuteNonQuery(); command.CommandText.ShouldBe("SELECT * FROM [foo].[Table]"); logger.Log.Trim() - .ShouldBe(string.Join(Environment.NewLine, new[] - { - "Info: Executing Database Server script 'Test'", - "Info: -------------", - "Info: | One | Two |", - "Info: -------------", - "Info: | A | B |", - "Info: -------------", - "Info:" - })); + .ShouldBe(string.Join(Environment.NewLine, + new[] + { + "Info: Executing Database Server script 'Test'", "Info: -------------", + "Info: | One | Two |", "Info: -------------", "Info: | A | B |", + "Info: -------------", "Info:" + })); } [Fact] @@ -250,14 +238,34 @@ public void logs_when_dbexception() }); dbConnection.CreateCommand().Returns(command); var logger = Substitute.For(); - logger.WhenForAnyArgs(x => x.WriteError(null, null)).Do(x => Console.WriteLine(x.Arg(), x.Arg())); + logger.WhenForAnyArgs(x => x.LogError(null, (object[]?)null)) + .Do(x => Console.WriteLine(x.Arg(), x.Arg())); - var executor = new SqlScriptExecutor(() => new TestConnectionManager(dbConnection, true), () => logger, null, () => true, null, () => Substitute.For()); + var executor = GetSqlScriptExecutor(command, log: logger); Action exec = () => executor.Execute(new SqlScript("Test", "create $schema$.Table")); exec.ShouldThrow(); command.Received().ExecuteNonQuery(); - logger.ReceivedWithAnyArgs().WriteError("", null); + logger.ReceivedWithAnyArgs().LogError("", null); + } + + static SqlScriptExecutor GetSqlScriptExecutor( + IDbCommand command, + bool variablesEnabled = true, + string? schema = null, + IUpgradeLog? log = null, + bool isScriptOutputLogged = false + ) + { + var dbConnection = Substitute.For(); + dbConnection.CreateCommand().Returns(command); + var testConnectionManager = new TestConnectionManager(dbConnection) { IsScriptOutputLogged = isScriptOutputLogged }; + log ??= new ConsoleUpgradeLog(); + testConnectionManager.OperationStarting(log, []); + + var executor = new SqlScriptExecutor(() => testConnectionManager, () => log, schema, () => variablesEnabled, + null, () => Substitute.For()); + return executor; } } } diff --git a/src/Tests/Tests.csproj b/src/Tests/Tests.csproj index 13d4abc..5d7d135 100644 --- a/src/Tests/Tests.csproj +++ b/src/Tests/Tests.csproj @@ -1,19 +1,19 @@ - net462;net8 + net8 Tests DbUp.SqlServer.Tests - + enable enable - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/dbup-sqlserver.sln b/src/dbup-sqlserver.sln index db152d8..e0eb44c 100644 --- a/src/dbup-sqlserver.sln +++ b/src/dbup-sqlserver.sln @@ -23,6 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{77157734-01D ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig dbup-sqlserver.sln.DotSettings = dbup-sqlserver.sln.DotSettings + Directory.Build.props = Directory.Build.props EndProjectSection EndProject Global diff --git a/src/dbup-sqlserver.sln.DotSettings b/src/dbup-sqlserver.sln.DotSettings index 2c78c0a..d3334fb 100644 --- a/src/dbup-sqlserver.sln.DotSettings +++ b/src/dbup-sqlserver.sln.DotSettings @@ -5,5 +5,8 @@ SQ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + True <data><IncludeFilters /><ExcludeFilters /></data> <data /> \ No newline at end of file diff --git a/src/dbup-sqlserver/AzureSqlConnectionManager.cs b/src/dbup-sqlserver/AzureSqlConnectionManager.cs index 008cba9..3008b01 100644 --- a/src/dbup-sqlserver/AzureSqlConnectionManager.cs +++ b/src/dbup-sqlserver/AzureSqlConnectionManager.cs @@ -1,54 +1,43 @@ using System.Collections.Generic; - -#if SUPPORTS_MICROSOFT_SQL_CLIENT +using System.Threading; using Microsoft.Data.SqlClient; -#else -using System.Data.SqlClient; -#endif - using DbUp.Engine.Transactions; using DbUp.Support; +using Azure.Core; +using Azure.Identity; -#if SUPPORTS_AZURE_AD -using Microsoft.Azure.Services.AppAuthentication; +namespace DbUp.SqlServer; -namespace DbUp.SqlServer +/// Manages an Azure Sql Server database connection. +public class AzureSqlConnectionManager : DatabaseConnectionManager { - /// Manages an Azure Sql Server database connection. - public class AzureSqlConnectionManager : DatabaseConnectionManager - { - public AzureSqlConnectionManager(string connectionString) - : this(connectionString, "https://database.windows.net/", null) - { } - - public AzureSqlConnectionManager(string connectionString, string resource) - : this(connectionString, resource, null) - { } - - public AzureSqlConnectionManager(string connectionString, string resource, string tenantId, string azureAdInstance = "https://login.microsoftonline.com/") - : base(new DelegateConnectionFactory((log, dbManager) => + public AzureSqlConnectionManager( + string connectionString, + TokenCredential tokenCredential, + string resource = "https://database.windows.net/", + string tenantId = null + ) + : base(new DelegateConnectionFactory((log, dbManager) => + { + var tokenContext = + new TokenRequestContext(scopes: new string[] { resource + "/.default" }, tenantId: tenantId); + var conn = new SqlConnection(connectionString) { - var conn = new SqlConnection(connectionString) - { - AccessToken = new AzureServiceTokenProvider(azureAdInstance: azureAdInstance).GetAccessTokenAsync(resource, tenantId) - .ConfigureAwait(false) - .GetAwaiter() - .GetResult() - }; + AccessToken = tokenCredential.GetToken(tokenContext, CancellationToken.None).Token + }; - if (dbManager.IsScriptOutputLogged) - conn.InfoMessage += (sender, e) => log.WriteInformation($"{{0}}", e.Message); + if (dbManager.IsScriptOutputLogged) + conn.InfoMessage += (sender, e) => log.LogInformation($"{{0}}", e.Message); - return conn; - })) - { } + return conn; + })) + { + } - public override IEnumerable SplitScriptIntoCommands(string scriptContents) - { - var commandSplitter = new SqlCommandSplitter(); - var scriptStatements = commandSplitter.SplitScriptIntoCommands(scriptContents); - return scriptStatements; - } + public override IEnumerable SplitScriptIntoCommands(string scriptContents) + { + var commandSplitter = new SqlCommandSplitter(); + var scriptStatements = commandSplitter.SplitScriptIntoCommands(scriptContents); + return scriptStatements; } } -#endif diff --git a/src/dbup-sqlserver/AzureSqlServerExtensions.cs b/src/dbup-sqlserver/AzureSqlServerExtensions.cs index 8477180..c93c4e8 100644 --- a/src/dbup-sqlserver/AzureSqlServerExtensions.cs +++ b/src/dbup-sqlserver/AzureSqlServerExtensions.cs @@ -1,9 +1,8 @@ -using System; +using Azure.Core; +using Azure.Identity; using DbUp.Builder; using DbUp.SqlServer; -#if SUPPORTS_AZURE_AD - /// Configuration extension methods for Azure SQL Server. // NOTE: DO NOT MOVE THIS TO A NAMESPACE // Since the class just contains extension methods, we leave it in the global:: namespace so that it is always available @@ -15,35 +14,21 @@ public static class AzureSqlServerExtensions /// Fluent helper type. /// The connection string. /// The SQL schema name to use. Defaults to 'dbo' if . - /// A builder for a database upgrader designed for Azure SQL Server databases. - public static UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity(this SupportedDatabases supported, string connectionString, string schema) - { - return supported.SqlDatabase(new AzureSqlConnectionManager(connectionString), schema); - } - - /// Creates an upgrader for Azure SQL Databases using Azure AD Integrated Security. - /// Fluent helper type. - /// The connection string. - /// The SQL schema name to use. Defaults to 'dbo' if . - /// A builder for a database upgrader designed for Azure SQL Server databases. - public static UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity(this SupportedDatabases supported, string connectionString, string schema, string resource) - { - return AzureSqlDatabaseWithIntegratedSecurity(supported, connectionString, schema, resource, null); - } - - /// Creates an upgrader for Azure SQL Databases using Azure AD Integrated Security. - /// Fluent helper type. - /// The connection string. - /// The SQL schema name to use. Defaults to 'dbo' if . - /// Resource to access. e.g. https://management.azure.com/. + /// The credentials used. If null, 'DefaultAzureCredential' is used. + /// Resource to access. e.g. https://database.windows.net/. /// If not specified, default tenant is used. Managed Service Identity REST protocols do not accept tenantId, so this can only be used with certificate and client secret based authentication. - /// Specify a value for clouds other than the Public Cloud. /// A builder for a database upgrader designed for Azure SQL Server databases. - public static UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity(this SupportedDatabases supported, string connectionString, string schema, string resource, string tenantId, string azureAdInstance = "https://login.microsoftonline.com/") + public static UpgradeEngineBuilder AzureSqlDatabaseWithIntegratedSecurity( + this SupportedDatabases supported, + string connectionString, + string schema = null, + TokenCredential tokenCredential = null, + string resource = "https://database.windows.net/", + string tenantId = null + ) { - return supported.SqlDatabase(new AzureSqlConnectionManager(connectionString, resource, tenantId, azureAdInstance), schema); + return supported.SqlDatabase( + new AzureSqlConnectionManager(connectionString, tokenCredential ?? new DefaultAzureCredential(), resource, tenantId), schema); } } #pragma warning restore CA1050 // Declare types in namespaces - -#endif diff --git a/src/dbup-sqlserver/Helpers/TemporarySqlDatabase.cs b/src/dbup-sqlserver/Helpers/TemporarySqlDatabase.cs index c53fd0c..8a84c2c 100644 --- a/src/dbup-sqlserver/Helpers/TemporarySqlDatabase.cs +++ b/src/dbup-sqlserver/Helpers/TemporarySqlDatabase.cs @@ -1,9 +1,5 @@ using System; -#if SUPPORTS_MICROSOFT_SQL_CLIENT using Microsoft.Data.SqlClient; -#else -using System.Data.SqlClient; -#endif using DbUp.Helpers; diff --git a/src/dbup-sqlserver/Properties/AssemblyInfo.cs b/src/dbup-sqlserver/Properties/AssemblyInfo.cs index 2cb2224..57508d6 100644 --- a/src/dbup-sqlserver/Properties/AssemblyInfo.cs +++ b/src/dbup-sqlserver/Properties/AssemblyInfo.cs @@ -2,7 +2,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] -[assembly: CLSCompliant(true)] +[assembly: CLSCompliant(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("8190b40b-ac5b-414f-8a00-9b6a2c12b010")] diff --git a/src/dbup-sqlserver/SqlConnectionManager.cs b/src/dbup-sqlserver/SqlConnectionManager.cs index 16f0500..d2dc6cf 100644 --- a/src/dbup-sqlserver/SqlConnectionManager.cs +++ b/src/dbup-sqlserver/SqlConnectionManager.cs @@ -1,9 +1,5 @@ using System.Collections.Generic; -#if SUPPORTS_MICROSOFT_SQL_CLIENT using Microsoft.Data.SqlClient; -#else -using System.Data.SqlClient; -#endif using DbUp.Engine.Transactions; using DbUp.Support; @@ -24,7 +20,7 @@ public SqlConnectionManager(string connectionString) var conn = new SqlConnection(connectionString); if (dbManager.IsScriptOutputLogged) - conn.InfoMessage += (sender, e) => log.WriteInformation($"{{0}}", e.Message); + conn.InfoMessage += (sender, e) => log.LogInformation($"{{0}}", e.Message); return conn; })) diff --git a/src/dbup-sqlserver/SqlContextUpgradeLog.cs b/src/dbup-sqlserver/SqlContextUpgradeLog.cs deleted file mode 100644 index 03419ba..0000000 --- a/src/dbup-sqlserver/SqlContextUpgradeLog.cs +++ /dev/null @@ -1,24 +0,0 @@ -#if SUPPORTS_SQL_CONTEXT -using Microsoft.SqlServer.Server; - -namespace DbUp.Engine.Output -{ - class SqlContextUpgradeLog : IUpgradeLog - { - public void WriteInformation(string format, params object[] args) - { - SqlContext.Pipe.Send("INFO: " + string.Format(format, args)); - } - - public void WriteError(string format, params object[] args) - { - SqlContext.Pipe.Send("ERROR: " + string.Format(format, args)); - } - - public void WriteWarning(string format, params object[] args) - { - SqlContext.Pipe.Send("WARN: " + string.Format(format, args)); - } - } -} -#endif \ No newline at end of file diff --git a/src/dbup-sqlserver/SqlScriptExecutor.cs b/src/dbup-sqlserver/SqlScriptExecutor.cs index df6653f..2e5a45c 100644 --- a/src/dbup-sqlserver/SqlScriptExecutor.cs +++ b/src/dbup-sqlserver/SqlScriptExecutor.cs @@ -1,10 +1,6 @@ using System; using System.Collections.Generic; -#if SUPPORTS_MICROSOFT_SQL_CLIENT using Microsoft.Data.SqlClient; -#else -using System.Data.SqlClient; -#endif using DbUp.Engine; using DbUp.Engine.Output; using DbUp.Engine.Transactions; @@ -45,9 +41,9 @@ protected override void ExecuteCommandsWithinExceptionHandler(int index, SqlScri } catch (SqlException sqlException) { - Log().WriteInformation("SQL exception has occurred in script: '{0}'", script.Name); - Log().WriteError("Script block number: {0}; Block line {1}; Procedure {2}; Number {3}; Message: {4}", index, sqlException.LineNumber, sqlException.Procedure, sqlException.Number, sqlException.Message); - Log().WriteError(sqlException.ToString()); + Log().LogInformation("SQL exception has occurred in script: '{0}'", script.Name); + Log().LogError("Script block number: {0}; Block line {1}; Procedure {2}; Number {3}; Message: {4}", index, sqlException.LineNumber, sqlException.Procedure, sqlException.Number, sqlException.Message); + Log().LogError(sqlException.ToString()); throw; } } diff --git a/src/dbup-sqlserver/SqlServerExtensions.cs b/src/dbup-sqlserver/SqlServerExtensions.cs index 48ca23e..528c97a 100644 --- a/src/dbup-sqlserver/SqlServerExtensions.cs +++ b/src/dbup-sqlserver/SqlServerExtensions.cs @@ -1,10 +1,7 @@ using System; +using System.Collections.Generic; using System.Data; -#if SUPPORTS_MICROSOFT_SQL_CLIENT using Microsoft.Data.SqlClient; -#else -using System.Data.SqlClient; -#endif using DbUp; using DbUp.Builder; using DbUp.Engine.Output; @@ -48,7 +45,6 @@ public static UpgradeEngineBuilder SqlDatabase(this SupportedDatabases supported return SqlDatabase(new SqlConnectionManager(connectionString), schema); } -#if SUPPORTS_AZURE_AD /// Creates an upgrader for SQL Server databases. /// Fluent helper type. /// The connection string. @@ -65,7 +61,6 @@ public static UpgradeEngineBuilder SqlDatabase(this SupportedDatabases supported return supported.SqlDatabase(new SqlConnectionManager(connectionString), schema); } -#endif /// /// Creates an upgrader for SQL Server databases. @@ -111,29 +106,15 @@ public static UpgradeEngineBuilder JournalToSqlTable(this UpgradeEngineBuilder b return builder; } -#if SUPPORTS_SQL_CONTEXT - /// - /// Logs to SqlContext.Pipe, for use with "context connection=true". - /// - /// The builder. - /// - /// The same builder - /// - public static UpgradeEngineBuilder LogToSqlContext(this UpgradeEngineBuilder builder) - { - return builder.LogTo(new SqlContextUpgradeLog()); - } -#endif - /// /// Ensures that the database specified in the connection string exists. /// /// 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()); } /// @@ -142,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); } /// @@ -154,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); } /// @@ -166,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); } /// @@ -179,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); } /// @@ -192,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); } /// @@ -205,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); } /// @@ -219,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) + { + 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 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, Func> createDbSqlCommandsFactory = null, bool checkOnly = false) { - SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, azureDatabaseEdition, collation); + return SqlDatabase(supported, connectionString, new ConsoleUpgradeLog(), commandTimeout, azureDatabaseEdition, collation, createDbSqlCommandsFactory, checkOnly); } /// @@ -234,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 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, IUpgradeLog logger, int timeout = -1, AzureDatabaseEdition azureDatabaseEdition = AzureDatabaseEdition.None, - string collation = null) + string collation = null, + Func> createDbSqlCommandsFactory = null, + bool checkOnly = false) { GetMasterConnectionStringBuilder(connectionString, logger, out var masterConnectionString, out var databaseName); @@ -255,48 +256,67 @@ 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) + IList createDbSqlCommands; + if (createDbSqlCommandsFactory == 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); + } + else + { + createDbSqlCommands = createDbSqlCommandsFactory(databaseName); } // Create the database... - using (var command = new SqlCommand(sqlCommandText, connection) - { - CommandType = CommandType.Text - }) + foreach (var sqlCommandText in createDbSqlCommands) { - 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.WriteInformation(@"Created database {0}", databaseName); + logger.LogInformation(@"Created database {0}", databaseName); + + return true; } } @@ -312,7 +332,7 @@ static bool DatabaseExistsIfConnectedToDirectly(IUpgradeLog logger, string conne } catch { - logger.WriteInformation("Could not connect to the database directly"); + logger.LogInformation("Could not connect to the database directly"); return false; } } @@ -364,7 +384,7 @@ public static void SqlDatabase(this SupportedDatabasesForDropDatabase supported, command.ExecuteNonQuery(); } - logger.WriteInformation("Dropped database {0}", databaseName); + logger.LogInformation("Dropped database {0}", databaseName); } } @@ -388,17 +408,14 @@ static void GetMasterConnectionStringBuilder(string connectionString, IUpgradeLo Password = "******" }; - logger.WriteInformation("Master ConnectionString => {0}", logMasterConnectionStringBuilder.ConnectionString); + logger.LogInformation("Master ConnectionString => {0}", logMasterConnectionStringBuilder.ConnectionString); masterConnectionString = masterConnectionStringBuilder.ConnectionString; } static bool DatabaseExists(SqlConnection connection, string databaseName) { - var sqlCommandText = string.Format - ( - @"SELECT TOP 1 case WHEN dbid IS NOT NULL THEN 1 ELSE 0 end FROM sys.sysdatabases WHERE name = '{0}';", - databaseName - ); + var sqlCommandText = + $@"SELECT TOP 1 case WHEN dbid IS NOT NULL THEN 1 ELSE 0 end FROM sys.sysdatabases WHERE name = '{databaseName}';"; // check to see if the database already exists.. using (var command = new SqlCommand(sqlCommandText, connection) diff --git a/src/dbup-sqlserver/dbup-sqlserver.csproj b/src/dbup-sqlserver/dbup-sqlserver.csproj index 8e6c3da..8340f0e 100644 --- a/src/dbup-sqlserver/dbup-sqlserver.csproj +++ b/src/dbup-sqlserver/dbup-sqlserver.csproj @@ -6,7 +6,7 @@ DbUp Contributors DbUp Copyright © DbUp Contributors 2015 - netstandard1.3;netstandard2.0;net462;net6.0 + netstandard2.0 dbup-sqlserver DbUp.SqlServer dbup-sqlserver @@ -16,43 +16,17 @@ dbup-icon.png - - - - - - - - - - - - - - - - - - - - - - - - - - - $(DefineConstants);SUPPORTS_SQL_CONTEXT;SUPPORTS_AZURE_AD + + true + true + embedded - - $(DefineConstants);SUPPORTS_AZURE_AD - + + + + - - $(DefineConstants);SUPPORTS_MICROSOFT_SQL_CLIENT - -