Skip to content

Commit

Permalink
fix #167: Ensure that a sql server database name that differs only by… (
Browse files Browse the repository at this point in the history
  • Loading branch information
wokket authored Jun 5, 2022
1 parent 87f1193 commit 0e67466
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
18 changes: 18 additions & 0 deletions grate.unittests/Generic/GenericDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,24 @@ public async Task Does_not_need_admin_connection_if_database_already_exists()
Assert.DoesNotThrowAsync(() => migrator.Migrate());
}

[Test]
public async Task Does_not_needlessly_apply_case_sensitive_database_name_checks_Issue_167()
{
// There's a bug where if the database name specified by the user differs from the actual database only by case then
// Grate currently attempts to create the database again, only for it to fail on the DBMS (Sql Server bug only).

var db = "CASEDATABASE";
await CreateDatabase(db);

// Check that the database has been created
IEnumerable<string> databasesBeforeMigration = await GetDatabases();
databasesBeforeMigration.Should().Contain(db);

await using var migrator = GetMigrator(GetConfiguration(db.ToLower(), true)); // ToLower is important here, this reproduces the bug in #167
// There should be no errors running the migration
Assert.DoesNotThrowAsync(() => migrator.Migrate());
}

protected virtual async Task CreateDatabase(string db)
{
using (new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled))
Expand Down
28 changes: 28 additions & 0 deletions grate/Migration/SqlServerDatabase.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
using System;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;
using System.Transactions;
using Dapper;
using grate.Configuration;
using grate.Infrastructure;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Logging;

using static System.Data.CommandType;

namespace grate.Migration;

public class SqlServerDatabase : AnsiSqlDatabase
Expand Down Expand Up @@ -68,4 +72,28 @@ WITH NOUNLOAD

Logger.LogInformation("Database {DbName} successfully restored from path {Path}.", DatabaseName, backupPath);
}

public override async Task<bool> DatabaseExists()
{
// For Bug #167. Sql Server is causing issues when the database name passed in differs only in case from one already existing on the server.
// There's currently no point adding to ISyntax for this as all the other DBMS's would just be a NOP.

// This should also mean that a SQL server running a Case Sensitive collation _also_ works as expected
var sql = $"select name from sys.databases where [name] = '{DatabaseName}'";
try
{
await OpenConnection();
var results = await Connection.QueryAsync<string>(sql, commandType: Text);
return results.Any();
}
catch (DbException ex)
{
Logger.LogDebug(ex, "An unexpected error occurred performing the CheckDatabaseExists check: {ErrorMessage}", ex.Message);
return false; // base method also returns false on any DbException
}
finally
{
await CloseConnection();
}
}
}

0 comments on commit 0e67466

Please sign in to comment.