Skip to content

Commit

Permalink
Issue #106: Oracle support
Browse files Browse the repository at this point in the history
* Oracle is a bit different to MS SQL, PostgreSQL and MariaDB, so there were a couple of changes
* Interpret 'Create database' as 'Create user' on Oracle DB, as a user with a schema
  is maybe the closest thing to a 'database' in other DBMSs
* Some restructuring/new extension points to make Oracle support
* Restructured and cleaned up code a bit
  • Loading branch information
erikbra committed Nov 13, 2021
1 parent 53019c0 commit 5a41eac
Show file tree
Hide file tree
Showing 45 changed files with 470 additions and 1,714 deletions.
14 changes: 7 additions & 7 deletions grate.unittests/Generic/GenericDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public abstract class GenericDatabase
[Test]
public async Task Is_created_if_confed_and_it_does_not_exist()
{
var db = "NewDatabase";
var db = "NEWDATABASE";

await using var migrator = GetMigrator(GetConfiguration(db, true));
await migrator.Migrate();
Expand All @@ -33,7 +33,7 @@ public async Task Is_created_if_confed_and_it_does_not_exist()
[Test]
public async Task Is_not_created_if_not_confed()
{
var db = "SomeOtherdatabase";
var db = "SOMEOTHERDATABASE";

IEnumerable<string> databasesBeforeMigration = await GetDatabases();
databasesBeforeMigration.Should().NotContain(db);
Expand All @@ -54,7 +54,7 @@ public async Task Is_not_created_if_not_confed()
[Test]
public async Task Does_not_error_if_confed_to_create_but_already_exists()
{
var db = "daataa";
var db = "DAATAA";

// Create the database manually before running the migration
await CreateDatabase(db);
Expand All @@ -72,7 +72,7 @@ public async Task Does_not_error_if_confed_to_create_but_already_exists()
[Test]
public async Task Does_not_need_admin_connection_if_database_already_exists()
{
var db = "datadatadatabase";
var db = "DATADATADATABASE";

// Create the database manually before running the migration
await CreateDatabase(db);
Expand All @@ -99,7 +99,7 @@ protected virtual async Task CreateDatabase(string db)
await using var conn = Context.CreateAdminDbConnection();
conn.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = Context.Syntax.CreateDatabase(db);
cmd.CommandText = Context.Syntax.CreateDatabase(db, TestConfig.Password(Context.ConnectionString(db)));
await cmd.ExecuteNonQueryAsync();
break;
}
Expand All @@ -111,7 +111,7 @@ protected virtual async Task CreateDatabase(string db)
protected virtual async Task<IEnumerable<string>> GetDatabases()
{
IEnumerable<string> databases =Enumerable.Empty<string>();
string sql = Context.Sql.SelectAllDatabases;
string sql = Context.Syntax.ListDatabases;

using (new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled))
{
Expand Down Expand Up @@ -142,7 +142,7 @@ private GrateConfiguration GetConfiguration(string databaseName, bool createData
CreateDatabase = createDatabase,
ConnectionString = Context.ConnectionString(databaseName),
AdminConnectionString = adminConnectionString ?? Context.AdminConnectionString,
KnownFolders = KnownFolders.In(new DirectoryInfo(@"C:\tmp\sql")),
KnownFolders = KnownFolders.In(TestConfig.CreateRandomTempDirectory()),
NonInteractive = true,
DatabaseType = Context.DatabaseType
};
Expand Down
45 changes: 9 additions & 36 deletions grate.unittests/Generic/GenericMigrationTables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public async Task Is_created_if_it_does_not_exist(string tableName)
var db = "MonoBonoJono";
var fullTableName = Context.Syntax.TableWithSchema("grate", tableName);

var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
var knownFolders = KnownFolders.In(TestConfig.CreateRandomTempDirectory());

await using (var migrator = GetMigrator(db, true, knownFolders))
await using (var migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}
Expand All @@ -52,10 +52,10 @@ public async Task Is_created_even_if_scripts_fail(string tableName)
var db = "DatabaseWithFailingScripts";
var fullTableName = Context.Syntax.TableWithSchema("grate", tableName);

var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
var knownFolders = KnownFolders.In(TestConfig.CreateRandomTempDirectory());
CreateInvalidSql(knownFolders.Up);

await using (var migrator = GetMigrator(db, true, knownFolders))
await using (var migrator = Context.GetMigrator(db, knownFolders))
{
try
{
Expand Down Expand Up @@ -83,15 +83,15 @@ public async Task Migration_does_not_fail_if_table_already_exists(string tableNa
{
var db = "MonoBonoJono";

var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
var knownFolders = KnownFolders.In(TestConfig.CreateRandomTempDirectory());

await using (var migrator = GetMigrator(db, true, knownFolders))
await using (var migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}

// Run migration again - make sure it does not throw an exception
await using (var migrator = GetMigrator(db, true, knownFolders))
await using (var migrator = Context.GetMigrator(db, knownFolders))
{
Assert.DoesNotThrowAsync(() => migrator.Migrate());
}
Expand All @@ -102,9 +102,9 @@ public async Task Inserts_version_in_version_table()
{
var db = "BooYaTribe";

var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
var knownFolders = KnownFolders.In(TestConfig.CreateRandomTempDirectory());

await using (var migrator = GetMigrator(db, true, knownFolders))
await using (var migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}
Expand All @@ -123,33 +123,6 @@ await using (var conn = Context.GetDbConnection(Context.ConnectionString(db)))
versions.FirstOrDefault().Should().Be("a.b.c.d");
}

private GrateMigrator GetMigrator(string databaseName, bool createDatabase, KnownFolders knownFolders)
{
var config = new GrateConfiguration()
{
CreateDatabase = createDatabase,
ConnectionString = Context.ConnectionString(databaseName),
AdminConnectionString = Context.AdminConnectionString,
Version = "a.b.c.d",
KnownFolders = knownFolders,
AlterDatabase = true,
NonInteractive = true,
DatabaseType = Context.DatabaseType
};

return Context.GetMigrator(config);

}

private static DirectoryInfo CreateRandomTempDirectory()
{
var dummyFile = Path.GetTempFileName();
File.Delete(dummyFile);

var scriptsDir = Directory.CreateDirectory(dummyFile);
return scriptsDir;
}

private static void CreateInvalidSql(MigrationsFolder? folder)
{
var dummySql = "SELECT TOP";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ public async Task Are_not_run_more_than_once_when_unchanged()
var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
CreateDummySql(knownFolders.Sprocs);

await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}
await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}
Expand All @@ -53,14 +53,14 @@ public async Task Are_run_again_if_changed_between_runs()
var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
CreateDummySql(knownFolders.Sprocs);

await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}

WriteSomeOtherSql(knownFolders.Sprocs);

await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}
Expand All @@ -78,7 +78,7 @@ await using (var conn = Context.CreateDbConnection(db))
using (new AssertionScope())
{
scripts.First().Should().Be(Context.Sql.SelectVersion);
scripts.Last().Should().Be(Context.Sql.SelectCurrentDatabase);
scripts.Last().Should().Be(Context.Syntax.CurrentDatabase);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public async Task Are_not_run_if_not_in_environment()
var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
CreateDummySql(knownFolders.Up, "1_.OTHER.filename.ENV.sql");

await using (migrator = Context.GetMigrator(db, true, knownFolders, "TEST"))
await using (migrator = Context.GetMigrator(db, knownFolders, "TEST"))
{
await migrator.Migrate();
}
Expand All @@ -48,7 +48,7 @@ await using (var conn = Context.CreateDbConnection(db))
var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
CreateDummySql(knownFolders.Up, "1_.OTHER.filename.ENV.sql");

await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}
Expand All @@ -75,7 +75,7 @@ public async Task Are_run_if_in_environment()
CreateDummySql(knownFolders.Up, "1_.TEST.filename.ENV.sql");
CreateDummySql(knownFolders.Up, "2_.TEST.ENV.otherfilename.sql");

await using (migrator = Context.GetMigrator(db, true, knownFolders, "TEST"))
await using (migrator = Context.GetMigrator(db, knownFolders, "TEST"))
{
await migrator.Migrate();
}
Expand Down Expand Up @@ -103,7 +103,7 @@ public async Task Non_environment_scripts_are_always_run()
CreateDummySql(knownFolders.Up, "2_.TEST.ENV.otherfilename.sql");
CreateDummySql(knownFolders.Up, "2_.TEST.ENV.somethingelse.sql");

await using (migrator = Context.GetMigrator(db, true, knownFolders, "PROD"))
await using (migrator = Context.GetMigrator(db, knownFolders, "PROD"))
{
await migrator.Migrate();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public async Task Are_run_every_time_even_when_unchanged()

for (var i = 0; i < 3; i++)
{
await using var migrator = Context.GetMigrator(db, true, knownFolders);
await using var migrator = Context.GetMigrator(db, knownFolders);
await migrator.Migrate();
}

Expand Down Expand Up @@ -77,7 +77,7 @@ public async Task Are_recognized_by_script_name()

for (var i = 0; i < 3; i++)
{
await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}
Expand Down Expand Up @@ -108,7 +108,7 @@ public async Task Are_not_run_in_baseline()

var path = knownFolders?.Views?.Path ?? throw new Exception("Config Fail");

WriteSql(path, "view.sql", "create view grate as select '1' as col;");
WriteSql(path, "view.sql", "create view grate as select '1' as col");

await using (var migrator = Context.GetMigrator(config))
{
Expand All @@ -130,14 +130,14 @@ await using (var migrator = Context.GetMigrator(config))

private void CreateEveryTimeScriptFile(MigrationsFolder? folder)
{
var dummySql = Context.Sql.SelectCurrentDatabase;
var dummySql = Context.Syntax.CurrentDatabase;
var path = MakeSurePathExists(folder);
WriteSql(path, "everytime.1_jalla.sql", dummySql);
}

private void CreateOtherEveryTimeScriptFile(MigrationsFolder? folder)
{
var dummySql = Context.Sql.SelectCurrentDatabase;
var dummySql = Context.Syntax.CurrentDatabase;
var path = MakeSurePathExists(folder);
WriteSql(path, "1_jalla.everytime.and.always.sql", dummySql);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public async Task Aborts_the_run_giving_an_error_message()
var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
CreateInvalidSql(knownFolders.Up);

await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
var ex = Assert.ThrowsAsync(Context.DbExceptionType, migrator.Migrate);
ex?.Message.Should().Be(ExpextedErrorMessageForInvalidSql);
Expand All @@ -43,7 +43,7 @@ public async Task Are_Inserted_Into_ScriptRunErrors_Table()
var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
CreateInvalidSql(knownFolders.Up);

await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected void CreateDummySql(MigrationsFolder? folder, string filename = "1_jal

protected void WriteSomeOtherSql(MigrationsFolder? folder, string filename = "1_jalla.sql")
{
var dummySql = Context.Sql.SelectCurrentDatabase;
var dummySql = Context.Syntax.CurrentDatabase;
var path = MakeSurePathExists(folder);
WriteSql(path, filename, dummySql);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ public async Task Are_not_run_more_than_once_when_unchanged()
var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
CreateDummySql(knownFolders.Up);

await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}
await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}
Expand All @@ -53,14 +53,14 @@ public async Task Fails_if_changed_between_runs()
var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
CreateDummySql(knownFolders.Up);

await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}

WriteSomeOtherSql(knownFolders.Up);

await using (migrator = Context.GetMigrator(db, true, knownFolders))
await using (migrator = Context.GetMigrator(db, knownFolders))
{
Assert.ThrowsAsync<OneTimeScriptChanged>(() => migrator.Migrate());
}
Expand Down Expand Up @@ -113,9 +113,12 @@ await using (var conn = Context.CreateDbConnection(db))
}

scripts.Should().HaveCount(2); //script run twice
scripts.Last().Should().Be(Context.Sql.SelectCurrentDatabase); // the script was re-run
scripts.Last().Should().Be(Context.Syntax.CurrentDatabase); // the script was re-run
}

protected virtual string CreateView1 => "create view grate as select '1' as col";
protected virtual string CreateView2 => "create view grate as select '2' as col";

[Test]
public async Task Ignores_and_warns_if_changed_between_runs_and_flag_set()
{
Expand All @@ -126,7 +129,7 @@ public async Task Ignores_and_warns_if_changed_between_runs_and_flag_set()
var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
var path = knownFolders?.Up?.Path ?? throw new Exception("Config Fail");

WriteSql(path, "token.sql", "create view grate as select '1' as col;");
WriteSql(path, "token.sql", CreateView1);

var config = Context.GetConfiguration(db, knownFolders) with
{
Expand All @@ -138,7 +141,7 @@ await using (migrator = Context.GetMigrator(config))
await migrator.Migrate();
}

WriteSql(path, "token.sql", "create view grate as select '2' as col;");
WriteSql(path, "token.sql", CreateView2);

await using (migrator = Context.GetMigrator(config))
{
Expand Down
12 changes: 8 additions & 4 deletions grate.unittests/Generic/Running_MigrationScripts/TokenScripts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@ namespace grate.unittests.Generic.Running_MigrationScripts
[TestFixture]
public abstract class TokenScripts : MigrationsScriptsBase
{

protected virtual string CreateDatabaseName => "create view grate as select '{{DatabaseName}}' as dbase";
protected virtual string CreateViewMyCustomToken => "create view grate as select '{{MyCustomToken}}' as dbase";

[Test]
public async Task EnsureTokensAreReplaced()
{
var db = TestConfig.RandomDatabase();
var db = TestConfig.RandomDatabase().ToUpper();

var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
var path = knownFolders?.Views?.Path ?? throw new Exception("Config Fail");
WriteSql(path, "token.sql", "create view grate as select '{{DatabaseName}}' as dbase;");
WriteSql(path, "token.sql", CreateDatabaseName);

await using (var migrator = Context.GetMigrator(db, true, knownFolders))
await using (var migrator = Context.GetMigrator(db, knownFolders))
{
await migrator.Migrate();
}
Expand All @@ -39,7 +43,7 @@ public async Task EnsureUserTokensAreReplaced()

var knownFolders = KnownFolders.In(CreateRandomTempDirectory());
var path = knownFolders?.Views?.Path ?? throw new Exception("Config Fail");
WriteSql(path, "token.sql", "create view grate as select '{{MyCustomToken}}' as dbase;");
WriteSql(path, "token.sql", CreateViewMyCustomToken);

var config = Context.GetConfiguration(db, knownFolders) with
{
Expand Down

0 comments on commit 5a41eac

Please sign in to comment.