diff --git a/Mayflower/ConnectionContext.cs b/Mayflower/ConnectionContext.cs index 5982325..155ecf6 100644 --- a/Mayflower/ConnectionContext.cs +++ b/Mayflower/ConnectionContext.cs @@ -1,4 +1,5 @@ -using System; +using MySql.Data.MySqlClient; +using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; @@ -9,6 +10,7 @@ namespace Mayflower public enum DatabaseProvider { SqlServer = 0, + MySql = 1 } class ConnectionContext : IDisposable @@ -37,10 +39,15 @@ internal ConnectionContext(Options options) switch (Provider) { case DatabaseProvider.SqlServer: - _sql = new SqlServerStatements(options.GetMigrationsTable()); + _sql = new SqlServerStatements(options.GetMigrationsTable(DatabaseProvider.SqlServer)); _connection = new SqlConnection(connStr); Database = new SqlConnectionStringBuilder(connStr).InitialCatalog; break; + case DatabaseProvider.MySql: + _sql = new MySqlStatements(options.GetMigrationsTable(DatabaseProvider.MySql)); + _connection = new MySqlConnection(connStr); + Database = new MySqlConnectionStringBuilder(connStr).Database; + break; default: throw new Exception("Unsupported DatabaseProvider " + options.Provider); } @@ -85,7 +92,11 @@ internal void Rollback() internal bool MigrationTableExists() { var cmd = _connection.NewCommand(_sql.DoesMigrationsTableExist); - return (int)cmd.ExecuteScalar() == 1; + + if (Provider == DatabaseProvider.MySql) + return (long)cmd.ExecuteScalar() == 1; + else + return (int)cmd.ExecuteScalar() == 1; } internal void CreateMigrationsTable() diff --git a/Mayflower/ISqlStatements.cs b/Mayflower/ISqlStatements.cs index f1890b7..dbb4c60 100644 --- a/Mayflower/ISqlStatements.cs +++ b/Mayflower/ISqlStatements.cs @@ -34,6 +34,42 @@ interface ISqlStatements string GetAlreadyRan { get; } } + class MySqlStatements : ISqlStatements + { + public Regex CommandSplitter { get; } = new Regex(@";", RegexOptions.IgnoreCase | RegexOptions.Multiline); + public string DoesMigrationsTableExist { get; } + public string CreateMigrationsTable { get; } + public string RenameMigration { get; } + public string UpdateMigrationHash { get; } + public string InsertMigration { get; } + public string GetAlreadyRan { get; } + + internal MySqlStatements(string migrationsTableName) + { + DoesMigrationsTableExist = $"SELECT count(*) FROM information_schema.tables WHERE table_name = '{migrationsTableName}';"; + + CreateMigrationsTable = $@" + CREATE TABLE {migrationsTableName} + ( + Id int not null AUTO_INCREMENT, + Filename nvarchar(260) not null, + Hash varchar(40) not null, + ExecutionDate datetime not null, + Duration int not null, + + constraint PK_{migrationsTableName} primary key clustered (Id), + constraint UX_{migrationsTableName}_Filename unique (Filename), + constraint UX_{migrationsTableName}_Hash unique (Hash) + ); + "; + + RenameMigration = $"update {migrationsTableName} set Filename = @Filename where Hash = @Hash;"; + UpdateMigrationHash = $"update {migrationsTableName} set Hash = @Hash, ExecutionDate = @ExecutionDate, Duration = @Duration where Filename = @Filename;"; + InsertMigration = $"insert {migrationsTableName} (Filename, Hash, ExecutionDate, Duration) values (@Filename, @Hash, @ExecutionDate, @Duration);"; + GetAlreadyRan = $"select * from {migrationsTableName} order by ExecutionDate, Id;"; + } + } + class SqlServerStatements : ISqlStatements { public Regex CommandSplitter { get; } = new Regex(@"^\s*GO\s*$", RegexOptions.IgnoreCase | RegexOptions.Multiline); @@ -49,19 +85,20 @@ internal SqlServerStatements(string migrationsTableName) DoesMigrationsTableExist = $"SELECT count(*) FROM sys.tables WHERE name = '{migrationsTableName}';"; CreateMigrationsTable = $@" -CREATE TABLE [{migrationsTableName}] -( - Id int not null Identity(1,1), - Filename nvarchar(260) not null, - Hash varchar(40) not null, - ExecutionDate datetime not null, - Duration int not null, + CREATE TABLE [{migrationsTableName}] + ( + Id int not null Identity(1,1), + Filename nvarchar(260) not null, + Hash varchar(40) not null, + ExecutionDate datetime not null, + Duration int not null, + + constraint PK_{migrationsTableName} primary key clustered (Id), + constraint UX_{migrationsTableName}_Filename unique (Filename), + constraint UX_{migrationsTableName}_Hash unique (Hash) + ); + "; - constraint PK_{migrationsTableName} primary key clustered (Id), - constraint UX_{migrationsTableName}_Filename unique (Filename), - constraint UX_{migrationsTableName}_Hash unique (Hash) -); -"; RenameMigration = $"update [{migrationsTableName}] set Filename = @Filename where Hash = @Hash;"; UpdateMigrationHash = $"update [{migrationsTableName}] set Hash = @Hash, ExecutionDate = @ExecutionDate, Duration = @Duration where Filename = @Filename;"; InsertMigration = $"insert [{migrationsTableName}] (Filename, Hash, ExecutionDate, Duration) values (@Filename, @Hash, @ExecutionDate, @Duration);"; diff --git a/Mayflower/Mayflower.csproj b/Mayflower/Mayflower.csproj index 9f8b250..80321ec 100644 --- a/Mayflower/Mayflower.csproj +++ b/Mayflower/Mayflower.csproj @@ -30,6 +30,9 @@ 4 + + ..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll + @@ -51,6 +54,10 @@ + + + +