Skip to content

Commit

Permalink
EnsureDatabase and DropDatabase implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeern committed Jul 31, 2024
1 parent a79be9c commit 94b22cb
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/Sample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ static int Main()
var config = GetConfig();
string connectionString = config.GetConnectionString("SampleFirebird");

// If you used `docker compose up` for creating a server and a database, the database already exists.
// You can see that a new database can be created using EnsureDatabase.For.FirebirdDatabase(connectionString) by changing the Database parameter (the fdb filename)
// in the connectionString in appsettings.json
// You can also try to drop a database by using DropDatabase.For.FirebirdDatabase(connectionString);
EnsureDatabase.For.FirebirdDatabase(connectionString);

var upgrader =
DeployChanges.To
.FirebirdDatabase(connectionString)
Expand Down
129 changes: 127 additions & 2 deletions src/dbup-firebird/FirebirdExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
using DbUp.Builder;
using System;
using System.IO;
using DbUp;
using DbUp.Builder;
using DbUp.Engine.Output;
using DbUp.Engine.Transactions;
using DbUp.Firebird;
using FirebirdSql.Data.FirebirdClient;

// ReSharper disable once CheckNamespace

Expand Down Expand Up @@ -49,4 +54,124 @@ public static UpgradeEngineBuilder FirebirdDatabase(IConnectionManager connectio
builder.WithPreprocessor(new FirebirdPreprocessor());
return builder;
}
}


//The code below concerning EnsureDatabase and DropDatabase is a modified version from a PR from Github user @hhindriks. Thank you for your contribution.

//Error codes from Firebird (see https://www.firebirdsql.org/pdfrefdocs/Firebird-2.1-ErrorCodes.pdf)
const int FbIoError = 335544344;
const int FbNetworkError = 335544721;
const int FbLockTimeout = 335544510;

/// <summary>
/// Ensures that the database specified in the connection string exists.
/// </summary>
/// <param name="supported">Fluent helper type.</param>
/// <param name="connectionString">The connection string.</param>
/// <param name="logger">The <see cref="DbUp.Engine.Output.IUpgradeLog"/> used to record actions.</param>
/// <returns></returns>
public static void FirebirdDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, IUpgradeLog logger = null)
{
logger ??= new ConsoleUpgradeLog();
var builder = new FbConnectionStringBuilder(connectionString);

if (builder.ServerType == FbServerType.Embedded)
{
//The code for the embedded servertype is currently not tested.
//Comes from the original PR from @hhindriks
if (!File.Exists(builder.Database))
{
FbConnection.CreateDatabase(builder.ToString());
logger.WriteInformation("Created database {0}", builder.Database);
}
else
{
logger.WriteInformation("Database {0} already exists", builder.Database);
}
}
else
{
using var conn = new FbConnection(builder.ToString());
try
{
conn.Open();
conn.Close();
logger.WriteInformation("Database {0} already exists", builder.Database);
}
catch (FbException ex) when (ex.ErrorCode == FbIoError)
{
FbConnection.CreateDatabase(builder.ToString());
logger.WriteInformation("Created database {0}", builder.Database);
}
catch (FbException ex) when (ex.ErrorCode == FbNetworkError)
{
logger.WriteError("Could not access server. The server: {0} is probably not started.", builder.DataSource);
throw;
}
catch (FbException)
{
logger.WriteError("Ensure Database: Unknown firebird error when trying to access the server: {0}.", builder.DataSource);
throw;
}
catch (Exception)
{
logger.WriteError("Ensure Database: Unknown error when trying to access the server: {0}.", builder.DataSource);
throw;
}
}
}

/// <summary>
/// Drop the database specified in the connection string.
/// </summary>
/// <param name="supported">Fluent helper type.</param>
/// <param name="connectionString">The connection string.</param>
/// <param name="logger">The <see cref="DbUp.Engine.Output.IUpgradeLog"/> used to record actions.</param>
/// <returns></returns>
public static void FirebirdDatabase(this SupportedDatabasesForDropDatabase supported, string connectionString, IUpgradeLog logger = null)
{
logger ??= new ConsoleUpgradeLog();
var builder = new FbConnectionStringBuilder(connectionString);

if (builder.ServerType == FbServerType.Embedded)
{
//The code for the embedded servertype is currently not tested.
//Comes from the original PR from @hhindriks
if (File.Exists(builder.Database))
{
FbConnection.DropDatabase(builder.ToString());
logger.WriteInformation("Dropped database {0}", builder.Database);
}
}
else
{
try
{
//There seems to be an error in the FirebirdClient when trying to drop a database that does not exist.
//It gives a NullRefException instead of the expected FbException.
FbConnection.DropDatabase(builder.ToString());
logger.WriteInformation("Dropped database {0}", builder.Database);
}
catch (FbException ex) when (ex.ErrorCode == FbIoError)
{
logger.WriteWarning("Nothing to Drop. No database found.");
}
catch (FbException ex) when (ex.ErrorCode == FbLockTimeout)
{
logger.WriteError("Can't drop database. Are there still an active connection?");
throw;
}
catch (FbException)
{
logger.WriteError("Drop Database: Unknown firebird error when trying to access the server: {0}.", builder.DataSource);
throw;
}
catch (Exception)
{
logger.WriteError("Drop Database: Unknown error when trying to access the server: {0}.", builder.DataSource);
throw;
}
}
}

}

0 comments on commit 94b22cb

Please sign in to comment.