Browse Source

Rename rerunable to repeatable

DEVOPS-1537-Update-dbo.Migrations-table-to-support-repeatable-migrations
Michal Checinski 2 years ago
parent
commit
95c14e467d
No known key found for this signature in database
GPG Key ID: 7658E89E8394A248
  1. 8
      util/Migrator/DbMigrator.cs
  2. 2
      util/Migrator/DbScripts/2023-08-24_00_AddRerunableColumnIndboMigrationsTable.sql
  3. 34
      util/Migrator/SqlTableJournalExtensions.cs
  4. 18
      util/MsSqlMigratorUtility/Program.cs

8
util/Migrator/DbMigrator.cs

@ -24,7 +24,7 @@ public class DbMigrator
} }
public bool MigrateMsSqlDatabaseWithRetries(bool enableLogging = true, public bool MigrateMsSqlDatabaseWithRetries(bool enableLogging = true,
bool rerunable = false, bool repeatable = false,
string folderName = "DbScripts", string folderName = "DbScripts",
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
@ -34,7 +34,7 @@ public class DbMigrator
{ {
try try
{ {
var success = MigrateDatabase(enableLogging, rerunable, folderName, cancellationToken); var success = MigrateDatabase(enableLogging, repeatable, folderName, cancellationToken);
return success; return success;
} }
catch (SqlException ex) catch (SqlException ex)
@ -56,7 +56,7 @@ public class DbMigrator
} }
public bool MigrateDatabase(bool enableLogging = true, public bool MigrateDatabase(bool enableLogging = true,
bool rerunable = false, bool repeatable = false,
string folderName = "DbScripts", string folderName = "DbScripts",
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
@ -102,7 +102,7 @@ public class DbMigrator
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
var builder = DeployChanges.To var builder = DeployChanges.To
.SqlDatabase(_connectionString) .SqlDatabase(_connectionString)
.JournalRerunableToSqlTable("dbo", "Migration", rerunable) .JournalRepeatableToSqlTable("dbo", "Migration", repeatable)
.WithScriptsAndCodeEmbeddedInAssembly(Assembly.GetExecutingAssembly(), .WithScriptsAndCodeEmbeddedInAssembly(Assembly.GetExecutingAssembly(),
s => s.Contains($".{folderName}.") && !s.Contains(".Archive.")) s => s.Contains($".{folderName}.") && !s.Contains(".Archive."))
.WithTransaction() .WithTransaction()

2
util/Migrator/DbScripts/2023-08-24_00_AddRerunableColumnIndboMigrationsTable.sql

@ -1,3 +1,3 @@
ALTER TABLE dbo.Migration ALTER TABLE dbo.Migration
ADD Rerunable bit NOT NULL DEFAULT 0 ADD Repeatable bit NOT NULL DEFAULT 0
GO GO

34
util/Migrator/SqlTableJournalExtensions.cs

@ -9,21 +9,21 @@ namespace Bit.Migrator;
public static class SqlTableJournalExtensions public static class SqlTableJournalExtensions
{ {
public static UpgradeEngineBuilder JournalRerunableToSqlTable(this UpgradeEngineBuilder builder, string schema, string table, bool rerunable = false) public static UpgradeEngineBuilder JournalRepeatableToSqlTable(this UpgradeEngineBuilder builder, string schema, string table, bool repeatable = false)
{ {
builder.Configure(c => c.Journal = new RerunableSqlTableJournal(() => c.ConnectionManager, () => c.Log, schema, table, rerunable)); builder.Configure(c => c.Journal = new RepeatableSqlTableJournal(() => c.ConnectionManager, () => c.Log, schema, table, repeatable));
return builder; return builder;
} }
} }
public class RerunableSqlTableJournal : SqlTableJournal public class RepeatableSqlTableJournal : SqlTableJournal
{ {
private bool Rerunable { get; set; } private bool Repeatable { get; set; }
public RerunableSqlTableJournal(Func<IConnectionManager> connectionManager, Func<IUpgradeLog> logger, string schema, string table, bool rerunable = false) public RepeatableSqlTableJournal(Func<IConnectionManager> connectionManager, Func<IUpgradeLog> logger, string schema, string table, bool repeatable = false)
: base(connectionManager, logger, schema, table) : base(connectionManager, logger, schema, table)
{ {
Rerunable = rerunable; Repeatable = repeatable;
} }
public override void StoreExecutedScript(SqlScript script, Func<IDbCommand> dbCommandFactory) public override void StoreExecutedScript(SqlScript script, Func<IDbCommand> dbCommandFactory)
@ -57,25 +57,25 @@ public class RerunableSqlTableJournal : SqlTableJournal
appliedParam.Value = DateTime.Now; appliedParam.Value = DateTime.Now;
command.Parameters.Add(appliedParam); command.Parameters.Add(appliedParam);
var rerunableParam = command.CreateParameter(); var repeatableParam = command.CreateParameter();
rerunableParam.ParameterName = "rerunable"; repeatableParam.ParameterName = "repeatable";
rerunableParam.Value = Rerunable; repeatableParam.Value = Repeatable;
command.Parameters.Add(rerunableParam); command.Parameters.Add(repeatableParam);
command.CommandText = GetInsertJournalEntrySql("@scriptName", "@applied", "@rerunable", "@scriptFileName"); command.CommandText = GetInsertJournalEntrySql("@scriptName", "@applied", "@repeatable", "@scriptFileName");
command.CommandType = CommandType.Text; command.CommandType = CommandType.Text;
return command; return command;
} }
protected string GetInsertJournalEntrySql(string @scriptName, string @applied, string @rerunable, string @scriptFileName) protected string GetInsertJournalEntrySql(string @scriptName, string @applied, string @repeatable, string @scriptFileName)
{ {
return @$"IF EXISTS (SELECT * FROM {FqSchemaTableName} WHERE Rerunable = 1 AND ScriptName like {@scriptFileName}) return @$"IF EXISTS (SELECT * FROM {FqSchemaTableName} WHERE Repeatable = 1 AND ScriptName like {@scriptFileName})
BEGIN BEGIN
UPDATE {FqSchemaTableName} SET ScriptName = {@scriptName}, Applied = {@applied}, Rerunable = {@rerunable} WHERE ScriptName like {@scriptFileName} UPDATE {FqSchemaTableName} SET ScriptName = {@scriptName}, Applied = {@applied}, Repeatable = {@repeatable} WHERE ScriptName like {@scriptFileName}
END END
ELSE ELSE
BEGIN BEGIN
insert into {FqSchemaTableName} (ScriptName, Applied, Rerunable) values ({@scriptName}, {@applied}, {@rerunable}) insert into {FqSchemaTableName} (ScriptName, Applied, Repeatable) values ({@scriptName}, {@applied}, {@repeatable})
END "; END ";
} }
@ -86,11 +86,11 @@ public class RerunableSqlTableJournal : SqlTableJournal
SELECT @columnVariable = SELECT @columnVariable =
CASE WHEN EXISTS CASE WHEN EXISTS
( (
SELECT 1 FROM sys.columns WHERE Name = N'Rerunable' AND Object_ID = Object_ID(N'dbo.Migration') SELECT 1 FROM sys.columns WHERE Name = N'Repeatable' AND Object_ID = Object_ID(N'dbo.Migration')
) )
THEN THEN
( (
'where [Rerunable] = 0' 'where [Repeatable] = 0'
) )
ELSE ELSE
( (

18
util/MsSqlMigratorUtility/Program.cs

@ -17,22 +17,22 @@ internal class Program
string databaseConnectionString, string databaseConnectionString,
[Option('v', "verbose", Description = "Enable verbose output of migrator logs")] [Option('v', "verbose", Description = "Enable verbose output of migrator logs")]
bool verbose = false, bool verbose = false,
[Option('r', "rerunable", Description = "Mark scripts as rerunable")] [Option('r', "repeatable", Description = "Mark scripts as repeatable")]
bool rerunable = false, bool repeatable = false,
[Option('f', "folder", Description = "Folder name of database scripts")] [Option('f', "folder", Description = "Folder name of database scripts")]
string folderName = "DbScripts") => MigrateDatabase(databaseConnectionString, verbose, rerunable, folderName); string folderName = "DbScripts") => MigrateDatabase(databaseConnectionString, verbose, repeatable, folderName);
private static void WriteUsageToConsole() private static void WriteUsageToConsole()
{ {
Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string>"); Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string>");
Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string> -v|--verbose (for verbose output of migrator logs)"); Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string> -v|--verbose (for verbose output of migrator logs)");
Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string> -r|--rerunable (for marking scripts as rerunable) -f|--folder <folder-name-in-migrator-project> (for specifying folder name of scripts)"); Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string> -r|--repeatable (for marking scripts as repeatable) -f|--folder <folder-name-in-migrator-project> (for specifying folder name of scripts)");
Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string> -v|--verbose (for verbose output of migrator logs) -r|--rerunable (for marking scripts as rerunable) -f|--folder <folder-name-in-migrator-project> (for specifying folder name of scripts)"); Console.WriteLine("Usage: MsSqlMigratorUtility <database-connection-string> -v|--verbose (for verbose output of migrator logs) -r|--repeatable (for marking scripts as repeatable) -f|--folder <folder-name-in-migrator-project> (for specifying folder name of scripts)");
} }
private static bool MigrateDatabase(string databaseConnectionString, bool verbose = false, bool rerunable = false, string folderName = "") private static bool MigrateDatabase(string databaseConnectionString, bool verbose = false, bool repeatable = false, string folderName = "")
{ {
Console.WriteLine($"rerunable: {rerunable}"); Console.WriteLine($"repeatable: {repeatable}");
Console.WriteLine($"folderName: {folderName}"); Console.WriteLine($"folderName: {folderName}");
var logger = CreateLogger(verbose); var logger = CreateLogger(verbose);
@ -40,11 +40,11 @@ internal class Program
bool success = false; bool success = false;
if (!string.IsNullOrWhiteSpace(folderName)) if (!string.IsNullOrWhiteSpace(folderName))
{ {
success = migrator.MigrateMsSqlDatabaseWithRetries(verbose, rerunable, folderName); success = migrator.MigrateMsSqlDatabaseWithRetries(verbose, repeatable, folderName);
} }
else else
{ {
success = migrator.MigrateMsSqlDatabaseWithRetries(verbose, rerunable); success = migrator.MigrateMsSqlDatabaseWithRetries(verbose, repeatable);
} }
return success; return success;

Loading…
Cancel
Save