Skip to content

Commit c824d96

Browse files
Aashik Nagadikeri HarishAashik Nagadikeri Harish
authored andcommitted
Added function to create postgres database with owner
1 parent 5cb8e38 commit c824d96

File tree

2 files changed

+82
-27
lines changed

2 files changed

+82
-27
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
[assembly: System.CLSCompliantAttribute(false)]
1+
using DbUp.Postgresql;
2+
3+
[assembly: System.CLSCompliantAttribute(false)]
24
[assembly: System.Runtime.InteropServices.ComVisibleAttribute(false)]
35
[assembly: System.Runtime.InteropServices.GuidAttribute("5ddc04cc-0bd3-421e-9ae4-9fd0e4f4ef04")]
46

@@ -16,6 +18,7 @@ public static void PostgresqlDatabase(this DbUp.SupportedDatabasesForEnsureDatab
1618
public static void PostgresqlDatabase(this DbUp.SupportedDatabasesForDropDatabase supported, string connectionString) { }
1719
public static void PostgresqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { }
1820
public static void PostgresqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.Postgresql.PostgresqlConnectionOptions connectionOptions) { }
21+
public static void PostgresqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.Postgresql.PostgresqlConnectionOptions connectionOptions, string owner) { }
1922
public static void PostgresqlDatabase(this DbUp.SupportedDatabasesForEnsureDatabase supported, string connectionString, DbUp.Engine.Output.IUpgradeLog logger) { }
2023
public static void PostgresqlDatabase(this DbUp.SupportedDatabasesForDropDatabase supported, string connectionString, System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { }
2124
public static void PostgresqlDatabase(this DbUp.SupportedDatabasesForDropDatabase supported, string connectionString, DbUp.Postgresql.PostgresqlConnectionOptions connectionOptions) { }

src/dbup-postgresql/PostgresqlExtensions.cs

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/// </summary>
1717
public static class PostgresqlExtensions
1818
{
19-
private static readonly string pattern= @"(?i)Search\s?Path=([^;]+)";
19+
private static readonly string pattern = @"(?i)Search\s?Path=([^;]+)";
2020
/// <summary>
2121
/// Creates an upgrader for PostgreSQL databases.
2222
/// </summary>
@@ -165,21 +165,55 @@ public static void PostgresqlDatabase(this SupportedDatabasesForEnsureDatabase s
165165
PostgresqlDatabase(supported, connectionString, logger, new PostgresqlConnectionOptions());
166166
}
167167

168+
/// <summary>
169+
/// Ensures that the database specified in the connection string exists.
170+
/// </summary>
171+
/// <param name="supported">Fluent helper type.</param>
172+
/// <param name="connectionString">The connection string.</param>
173+
/// <param name="logger">The <see cref="DbUp.Engine.Output.IUpgradeLog"/> used to record actions.</param>
174+
/// <param name="certificate">Certificate for securing connection.</param>
175+
/// <returns></returns>
168176
public static void PostgresqlDatabase(this SupportedDatabasesForEnsureDatabase supported, string connectionString, IUpgradeLog logger, X509Certificate2 certificate)
169177
{
170178
var options = new PostgresqlConnectionOptions
171-
{
179+
{
172180
ClientCertificate = certificate
173181
};
174182
PostgresqlDatabase(supported, connectionString, logger, options);
175183
}
176184

185+
/// <summary>
186+
/// Ensures that the database specified in the connection string exists.
187+
/// </summary>
188+
/// <param name="supported">Fluent helper type.</param>
189+
/// <param name="connectionString">The connection string.</param>
190+
/// <param name="logger">The <see cref="DbUp.Engine.Output.IUpgradeLog"/> used to record actions.</param>
191+
/// <param name="connectionOptions">Connection SSL to customize SSL behaviour</param>
177192
public static void PostgresqlDatabase(
178-
this SupportedDatabasesForEnsureDatabase supported,
179-
string connectionString,
180-
IUpgradeLog logger,
193+
this SupportedDatabasesForEnsureDatabase supported,
194+
string connectionString,
195+
IUpgradeLog logger,
181196
PostgresqlConnectionOptions connectionOptions
182197
)
198+
{
199+
PostgresqlDatabase(supported, connectionString, logger, connectionOptions, null);
200+
}
201+
202+
/// <summary>
203+
/// Ensures that the database specified in the connection string exists, assigning an owner at creation time.
204+
/// </summary>
205+
/// <param name="supported">Fluent helper type.</param>
206+
/// <param name="connectionString">The connection string.</param>
207+
/// <param name="logger">The <see cref="DbUp.Engine.Output.IUpgradeLog"/> used to record actions.</param>
208+
/// <param name="connectionOptions">Connection SSL to customize SSL behaviour</param>
209+
/// <param name="owner">Role to own the new database during creation (adds 'WITH OWNER = "role"').</param>
210+
public static void PostgresqlDatabase(
211+
this SupportedDatabasesForEnsureDatabase supported,
212+
string connectionString,
213+
IUpgradeLog logger,
214+
PostgresqlConnectionOptions connectionOptions,
215+
string owner
216+
)
183217
{
184218
if (supported == null) throw new ArgumentNullException("supported");
185219

@@ -191,14 +225,16 @@ PostgresqlConnectionOptions connectionOptions
191225
if (logger == null) throw new ArgumentNullException("logger");
192226

193227
var masterConnectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString);
194-
228+
195229
var databaseName = masterConnectionStringBuilder.Database;
196230

197231
if (string.IsNullOrEmpty(databaseName) || databaseName.Trim() == string.Empty)
198232
{
199233
throw new InvalidOperationException("The connection string does not specify a database name.");
200234
}
201235

236+
owner = string.IsNullOrWhiteSpace(owner) ? masterConnectionStringBuilder.Username : owner;
237+
202238
masterConnectionStringBuilder.Database = connectionOptions.MasterDatabaseName;
203239

204240
var logMasterConnectionStringBuilder = new NpgsqlConnectionStringBuilder(masterConnectionStringBuilder.ConnectionString);
@@ -218,9 +254,9 @@ PostgresqlConnectionOptions connectionOptions
218254

219255
// check to see if the database already exists..
220256
using (var command = new NpgsqlCommand(sqlCommandText, connection)
221-
{
222-
CommandType = CommandType.Text
223-
})
257+
{
258+
CommandType = CommandType.Text
259+
})
224260
{
225261
var results = Convert.ToInt32(command.ExecuteScalar());
226262

@@ -231,13 +267,29 @@ PostgresqlConnectionOptions connectionOptions
231267
}
232268
}
233269

234-
sqlCommandText = $"create database \"{databaseName}\";";
270+
sqlCommandText = $"select 1 from pg_roles where rolname = \'{owner}\' limit 1;";
271+
// check to see if the owner exists..
272+
using (var command = new NpgsqlCommand(sqlCommandText, connection)
273+
{
274+
CommandType = CommandType.Text
275+
})
276+
{
277+
var results = Convert.ToInt32(command.ExecuteScalar());
278+
279+
// if the owner role does not exist, we throw an exception.
280+
if (results == 0)
281+
{
282+
throw new InvalidOperationException($"PostgreSQL role '{owner}' does not exist.");
283+
}
284+
}
285+
286+
sqlCommandText = $"create database \"{databaseName}\" with owner = \"{owner}\";";
235287

236288
// Create the database...
237289
using (var command = new NpgsqlCommand(sqlCommandText, connection)
238-
{
239-
CommandType = CommandType.Text
240-
})
290+
{
291+
CommandType = CommandType.Text
292+
})
241293
{
242294
command.ExecuteNonQuery();
243295
}
@@ -319,7 +371,7 @@ PostgresqlConnectionOptions connectionOptions
319371

320372
var masterConnectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString);
321373

322-
var databaseName = masterConnectionStringBuilder.Database;
374+
var databaseName = masterConnectionStringBuilder.Database;
323375

324376
if (string.IsNullOrEmpty(databaseName) || databaseName.Trim() == string.Empty)
325377
{
@@ -351,9 +403,9 @@ PostgresqlConnectionOptions connectionOptions
351403

352404
// check to see if the database already exists..
353405
using (var command = new NpgsqlCommand(sqlCommandText, connection)
354-
{
355-
CommandType = CommandType.Text
356-
})
406+
{
407+
CommandType = CommandType.Text
408+
})
357409
{
358410
var results = Convert.ToInt32(command.ExecuteScalar());
359411

@@ -368,9 +420,9 @@ PostgresqlConnectionOptions connectionOptions
368420
// prevent new connections to the database
369421
sqlCommandText = $"alter database \"{databaseName}\" with ALLOW_CONNECTIONS false;";
370422
using (var command = new NpgsqlCommand(sqlCommandText, connection)
371-
{
372-
CommandType = CommandType.Text
373-
})
423+
{
424+
CommandType = CommandType.Text
425+
})
374426
{
375427
command.ExecuteNonQuery();
376428
}
@@ -380,9 +432,9 @@ PostgresqlConnectionOptions connectionOptions
380432
// terminate all existing connections to the database
381433
sqlCommandText = $"select pg_terminate_backend(pg_stat_activity.pid) from pg_stat_activity where pg_stat_activity.datname = \'{databaseName}\';";
382434
using (var command = new NpgsqlCommand(sqlCommandText, connection)
383-
{
384-
CommandType = CommandType.Text
385-
})
435+
{
436+
CommandType = CommandType.Text
437+
})
386438
{
387439
command.ExecuteNonQuery();
388440
}
@@ -393,9 +445,9 @@ PostgresqlConnectionOptions connectionOptions
393445

394446
// drop the database
395447
using (var command = new NpgsqlCommand(sqlCommandText, connection)
396-
{
397-
CommandType = CommandType.Text
398-
})
448+
{
449+
CommandType = CommandType.Text
450+
})
399451
{
400452
command.ExecuteNonQuery();
401453
}

0 commit comments

Comments
 (0)