Skip to content

Commit c77ddde

Browse files
committed
Merge branch 'main' into release/6.0.0
# Conflicts: # src/Tests/ApprovalFiles/NoPublicApiChanges.Run.Net.verified.cs
2 parents f0ac9b7 + ff15148 commit c77ddde

File tree

7 files changed

+181
-7
lines changed

7 files changed

+181
-7
lines changed

README.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
[![Prerelease](https://img.shields.io/nuget/vpre/dbup-firebird?color=orange&label=prerelease)](https://www.nuget.org/packages/dbup-firebird)
55

66
# DbUp Firebird support
7-
DbUp is a .NET library that helps you to deploy changes to SQL Server databases. It tracks which SQL scripts have been run already, and runs the change scripts that are needed to get your database up to date.
7+
DbUp is a .NET library that helps you to deploy changes to relational databases. It tracks which SQL scripts have been run already, and runs the change scripts that are needed to get your database up to date.
8+
This Provider is for deploying to Firebird databases.
89

910
## Getting Help
1011
To learn more about DbUp check out the [documentation](https://dbup.readthedocs.io/en/latest/)
@@ -13,4 +14,24 @@ Please only log issue related to Firebird support in this repo. For cross cuttin
1314

1415
# Contributing
1516

16-
See the [readme in our main repo](https://github.com/DbUp/DbUp/blob/master/README.md) for how to get started and contribute.
17+
See the [readme in our main repo](https://github.com/DbUp/DbUp/blob/master/README.md) for how to get started and contribute.
18+
19+
# Quirks concerning the Firebird implementation
20+
21+
The Journal Table for Firebird is called `"schemaversions"` i.e. with quotes. This can be confusing since other providers do not use quotes.
22+
23+
It will not be fixed because of backwards compatibility. You can check the content of the table by using
24+
25+
```sql
26+
select * from "schemaversions"
27+
```
28+
29+
In a new project you can also choose another name for the JournalTable instead like this:
30+
31+
```csharp
32+
public static UpgradeEngineBuilder JournalToFirebirdTable(this UpgradeEngineBuilder builder)
33+
{
34+
builder.Configure(c => c.Journal = new FirebirdTableJournal(() => c.ConnectionManager, () => c.Log, "ABetterTableName"));
35+
return builder;
36+
37+
```

src/Sample/Program.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ static int Main()
1313
var config = GetConfig();
1414
string connectionString = config.GetConnectionString("SampleFirebird");
1515

16+
// If you used `docker compose up` for creating a server and a database, the database already exists.
17+
// You can see that a new database can be created using EnsureDatabase.For.FirebirdDatabase(connectionString) by changing the Database parameter (the fdb filename)
18+
// in the connectionString in appsettings.json
19+
// You can also try to drop a database by using DropDatabase.For.FirebirdDatabase(connectionString);
20+
EnsureDatabase.For.FirebirdDatabase(connectionString);
21+
1622
var upgrader =
1723
DeployChanges.To
1824
.FirebirdDatabase(connectionString)

src/Sample/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
To try this sample that demonstrates the use of DbUp for Firebird you can install docker and run `docker compose up` from a terminal in this folder.
2+
3+
After that you can run the sample project and notice the scripts are run against the fbsample.fdb database
4+
5+
The Firebird server uses the latest jacobalberty/firebird image from Dockerhub. At the time of writing the latest image uses the v4.0.1 version of the firebird server

src/Sample/appsettings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"ConnectionStrings": {
3-
"SampleFirebird": "User=SOMEUSER;Password=SOMEPWD;Database=c:\\somedb.fdb;DataSource=SOMESERVERNAME;Port=SOMEPORT;Dialect=3;Charset=ISO8859_1;ServerType=0;Connection lifetime=15;Pooling=true;MinPoolSize=0;MaxPoolSize=50;"
4-
}
2+
"ConnectionStrings": {
3+
"SampleFirebird": "User=SYSDBA;Password=firebirdsample;Database=/firebird/data/fbsample.fdb;DataSource=localhost;Port=3050;Dialect=3;Charset=ISO8859_1;ServerType=0;Connection lifetime=15;Pooling=true;MinPoolSize=0;MaxPoolSize=50;"
4+
}
55
}

src/Sample/docker-compose.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
services:
2+
firebird:
3+
image: jacobalberty/firebird
4+
container_name: dbupfirebird
5+
hostname: firebird
6+
environment:
7+
- ISC_USER=SYSDBA
8+
- ISC_PASSWORD=firebirdsample
9+
- FIREBIRD_DATABASE=fbsample.fdb
10+
- FIREBIRD_USER=sampleuser
11+
- FIREBIRD_PASSWORD=firebirdsample
12+
ports:
13+
- 3050:3050
14+
volumes:
15+
- ./firebird/intl/:/firebird/intl

src/Tests/ApprovalFiles/NoPublicApiChanges.Run.approved.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ public static class FirebirdExtensions
66
public static DbUp.Builder.UpgradeEngineBuilder FirebirdDatabase(DbUp.Engine.Transactions.IConnectionManager connectionManager) { }
77
public static DbUp.Builder.UpgradeEngineBuilder FirebirdDatabase(this DbUp.Builder.SupportedDatabases supported, string connectionString) { }
88
public static DbUp.Builder.UpgradeEngineBuilder FirebirdDatabase(this DbUp.Builder.SupportedDatabases supported, DbUp.Engine.Transactions.IConnectionManager connectionManager) { }
9+
public static void FirebirdDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.Engine.Output.IUpgradeLog logger = null) { }
10+
public static void FirebirdDatabase(this DbUp.SupportedDatabasesForDropDatabase supported, string connectionString, DbUp.Engine.Output.IUpgradeLog logger = null) { }
911
}
1012
namespace DbUp.Firebird
1113
{

src/dbup-firebird/FirebirdExtensions.cs

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
using DbUp.Builder;
1+
using System;
2+
using System.IO;
3+
using DbUp;
4+
using DbUp.Builder;
5+
using DbUp.Engine.Output;
26
using DbUp.Engine.Transactions;
37
using DbUp.Firebird;
8+
using FirebirdSql.Data.FirebirdClient;
49

510
// ReSharper disable once CheckNamespace
611

@@ -49,4 +54,124 @@ public static UpgradeEngineBuilder FirebirdDatabase(IConnectionManager connectio
4954
builder.WithPreprocessor(new FirebirdPreprocessor());
5055
return builder;
5156
}
52-
}
57+
58+
59+
//The code below concerning EnsureDatabase and DropDatabase is a modified version from a PR from Github user @hhindriks. Thank you for your contribution.
60+
61+
//Error codes from Firebird (see https://www.firebirdsql.org/pdfrefdocs/Firebird-2.1-ErrorCodes.pdf)
62+
const int FbIoError = 335544344;
63+
const int FbNetworkError = 335544721;
64+
const int FbLockTimeout = 335544510;
65+
66+
/// <summary>
67+
/// Ensures that the database specified in the connection string exists.
68+
/// </summary>
69+
/// <param name="supported">Fluent helper type.</param>
70+
/// <param name="connectionString">The connection string.</param>
71+
/// <param name="logger">The <see cref="DbUp.Engine.Output.IUpgradeLog"/> used to record actions.</param>
72+
/// <returns></returns>
73+
public static void FirebirdDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, IUpgradeLog logger = null)
74+
{
75+
logger ??= new ConsoleUpgradeLog();
76+
var builder = new FbConnectionStringBuilder(connectionString);
77+
78+
if (builder.ServerType == FbServerType.Embedded)
79+
{
80+
//The code for the embedded servertype is currently not tested.
81+
//Comes from the original PR from @hhindriks
82+
if (!File.Exists(builder.Database))
83+
{
84+
FbConnection.CreateDatabase(builder.ToString());
85+
logger.LogInformation("Created database {0}", builder.Database);
86+
}
87+
else
88+
{
89+
logger.LogInformation("Database {0} already exists", builder.Database);
90+
}
91+
}
92+
else
93+
{
94+
using var conn = new FbConnection(builder.ToString());
95+
try
96+
{
97+
conn.Open();
98+
conn.Close();
99+
logger.LogInformation("Database {0} already exists", builder.Database);
100+
}
101+
catch (FbException ex) when (ex.ErrorCode == FbIoError)
102+
{
103+
FbConnection.CreateDatabase(builder.ToString());
104+
logger.LogInformation("Created database {0}", builder.Database);
105+
}
106+
catch (FbException ex) when (ex.ErrorCode == FbNetworkError)
107+
{
108+
logger.LogError("Could not access server. The server: {0} is probably not started.", builder.DataSource);
109+
throw;
110+
}
111+
catch (FbException)
112+
{
113+
logger.LogError("Ensure Database: Unknown firebird error when trying to access the server: {0}.", builder.DataSource);
114+
throw;
115+
}
116+
catch (Exception)
117+
{
118+
logger.LogError("Ensure Database: Unknown error when trying to access the server: {0}.", builder.DataSource);
119+
throw;
120+
}
121+
}
122+
}
123+
124+
/// <summary>
125+
/// Drop the database specified in the connection string.
126+
/// </summary>
127+
/// <param name="supported">Fluent helper type.</param>
128+
/// <param name="connectionString">The connection string.</param>
129+
/// <param name="logger">The <see cref="DbUp.Engine.Output.IUpgradeLog"/> used to record actions.</param>
130+
/// <returns></returns>
131+
public static void FirebirdDatabase(this SupportedDatabasesForDropDatabase supported, string connectionString, IUpgradeLog logger = null)
132+
{
133+
logger ??= new ConsoleUpgradeLog();
134+
var builder = new FbConnectionStringBuilder(connectionString);
135+
136+
if (builder.ServerType == FbServerType.Embedded)
137+
{
138+
//The code for the embedded servertype is currently not tested.
139+
//Comes from the original PR from @hhindriks
140+
if (File.Exists(builder.Database))
141+
{
142+
FbConnection.DropDatabase(builder.ToString());
143+
logger.LogInformation("Dropped database {0}", builder.Database);
144+
}
145+
}
146+
else
147+
{
148+
try
149+
{
150+
//There seems to be an error in the FirebirdClient when trying to drop a database that does not exist.
151+
//It gives a NullRefException instead of the expected FbException.
152+
FbConnection.DropDatabase(builder.ToString());
153+
logger.LogInformation("Dropped database {0}", builder.Database);
154+
}
155+
catch (FbException ex) when (ex.ErrorCode == FbIoError)
156+
{
157+
logger.LogWarning("Nothing to Drop. No database found.");
158+
}
159+
catch (FbException ex) when (ex.ErrorCode == FbLockTimeout)
160+
{
161+
logger.LogError("Can't drop database. Are there still an active connection?");
162+
throw;
163+
}
164+
catch (FbException)
165+
{
166+
logger.LogError("Drop Database: Unknown firebird error when trying to access the server: {0}.", builder.DataSource);
167+
throw;
168+
}
169+
catch (Exception)
170+
{
171+
logger.LogError("Drop Database: Unknown error when trying to access the server: {0}.", builder.DataSource);
172+
throw;
173+
}
174+
}
175+
}
176+
177+
}

0 commit comments

Comments
 (0)