diff --git a/README.md b/README.md index 3765f8f..5ed987e 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ Respawn is a small utility to help in resetting test databases to a clean state. Instead of deleting data at the end of a test or rolling back a transaction, Respawn [resets the database back to a clean checkpoint](http://lostechies.com/jimmybogard/2013/06/18/strategies-for-isolating-the-database-in-tests/) by intelligently deleting data from tables. -To use, create a `Checkpoint` and initialize with tables you want to skip, or schemas you want to keep/ignore: +To use, create a `Respawner` and initialize with tables you want to skip, or schemas you want to keep/ignore: ```csharp -private static Checkpoint checkpoint = new Checkpoint +var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { TablesToIgnore = new Table[] { @@ -23,23 +23,23 @@ private static Checkpoint checkpoint = new Checkpoint { "RoundhousE" } -}; +}); ``` Or if you want to use a different database: ```csharp -private static Checkpoint checkpoint = new Checkpoint +var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { SchemasToInclude = new [] { "public" }, DbAdapter = DbAdapter.Postgres -}; +}); ``` In your tests, in the fixture setup, reset your checkpoint: ```csharp -await checkpoint.Reset("MyConnectionStringName"); +await respawner.ResetAsync("MyConnectionStringName"); ``` or if you're using a database besides SQL Server, pass an open `DbConnection`: ```csharp @@ -47,7 +47,7 @@ using (var conn = new NpgsqlConnection("ConnectionString")) { await conn.OpenAsync(); - await checkpoint.Reset(conn); + await respawner.ResetAsync(conn); } ``` diff --git a/Respawn.DatabaseTests/InformixTests.cs b/Respawn.DatabaseTests/InformixTests.cs index 7f448e6..70127e1 100644 --- a/Respawn.DatabaseTests/InformixTests.cs +++ b/Respawn.DatabaseTests/InformixTests.cs @@ -71,12 +71,12 @@ public async Task ShouldDeleteData() command.CommandText = "SELECT COUNT(1) FROM Foo"; command.ExecuteScalar().ShouldBe(100); - var checkPoint = new Checkpoint + var checkPoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Informix, SchemasToInclude = new[] { "informix" } - }; - await checkPoint.Reset(_connection); + }); + await checkPoint.ResetAsync(_connection); command.ExecuteScalar().ShouldBe(0); } @@ -97,13 +97,13 @@ public async Task ShouldIgnoreTables() command.ExecuteNonQuery(); command.Parameters.Clear(); } - var checkPoint = new Checkpoint() + var checkPoint = await Respawner.CreateAsync(_connection, new RespawnerOptions() { DbAdapter = DbAdapter.Informix, SchemasToInclude = new[] { "informix" }, TablesToIgnore = new Table[] { "foo" } - }; - await checkPoint.Reset(_connection); + }); + await checkPoint.ResetAsync(_connection); command.CommandText = "SELECT COUNT(1) FROM Foo"; command.ExecuteScalar().ShouldBe(100); @@ -138,14 +138,14 @@ FOREIGN KEY (FooValue) REFERENCES Foo(Value) command.CommandText = "SELECT COUNT(1) FROM Bar"; command.ExecuteScalar().ShouldBe(100); - var checkPoint = new Checkpoint + var checkPoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Informix, SchemasToInclude = new[] { "informix" } - }; + }); try { - await checkPoint.Reset(_connection); + await checkPoint.ResetAsync(_connection); } catch { @@ -201,14 +201,14 @@ ParentId INT NULL command.CommandText = "SELECT COUNT(1) FROM Child"; command.ExecuteScalar().ShouldBe(100); - var checkPoint = new Checkpoint + var checkPoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Informix, SchemasToInclude = new[] { "informix" } - }; + }); try { - await checkPoint.Reset(_connection); + await checkPoint.ResetAsync(_connection); } catch { @@ -249,14 +249,14 @@ ParentId INT NULL command.CommandText = "SELECT COUNT(1) FROM Foo"; command.ExecuteScalar().ShouldBe(100); - var checkPoint = new Checkpoint + var checkPoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Informix, SchemasToInclude = new[] { "informix" } - }; + }); try { - await checkPoint.Reset(_connection); + await checkPoint.ResetAsync(_connection); } catch { @@ -329,14 +329,14 @@ public async Task ShouldHandleComplexCycles() command.CommandText = "SELECT COUNT(1) FROM F"; command.ExecuteScalar().ShouldBe(1); - var checkPoint = new Checkpoint + var checkPoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Informix, SchemasToInclude = new[] { "informix" } - }; + }); try { - await checkPoint.Reset(_connection); + await checkPoint.ResetAsync(_connection); } catch { @@ -381,14 +381,14 @@ public async Task ShouldExcludeSchemas() command.Parameters.Clear(); } - var checkPoint = new Checkpoint + var checkPoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Informix, SchemasToExclude = new[] { user_1 } - }; + }); try { - await checkPoint.Reset(_connection); + await checkPoint.ResetAsync(_connection); } catch { @@ -425,14 +425,14 @@ public async Task ShouldIncludeSchemas() command.Parameters.Clear(); } - var checkPoint = new Checkpoint + var checkPoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Informix, SchemasToInclude = new[] { user_2 } - }; + }); try { - await checkPoint.Reset(_connection); + await checkPoint.ResetAsync(_connection); } catch { diff --git a/Respawn.DatabaseTests/MySqlTests.cs b/Respawn.DatabaseTests/MySqlTests.cs index e09dd7c..7407d38 100644 --- a/Respawn.DatabaseTests/MySqlTests.cs +++ b/Respawn.DatabaseTests/MySqlTests.cs @@ -56,12 +56,12 @@ public async Task ShouldDeleteData() _database.ExecuteScalar("SELECT COUNT(1) FROM Foo").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql, SchemasToInclude = new[] { "MySqlTests" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM Foo").ShouldBe(0); } @@ -114,12 +114,12 @@ PRIMARY KEY (`BarValue`), _database.ExecuteScalar("SELECT COUNT(1) FROM Bar").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM Bob").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql, SchemasToInclude = new[] { "MySqlTests" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM Foo").ShouldBe(0); _database.ExecuteScalar("SELECT COUNT(1) FROM Bar").ShouldBe(0); @@ -140,14 +140,14 @@ public async Task ShouldHandleSelfRelationships() _database.ExecuteScalar("SELECT COUNT(1) FROM foo").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql, SchemasToInclude = new[] { "MySqlTests" } - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -179,12 +179,12 @@ public async Task ShouldHandleCircularRelationships() _database.ExecuteScalar("SELECT COUNT(1) FROM parent").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM child").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql, SchemasToInclude = new[] { "MySqlTests" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM parent").ShouldBe(0); _database.ExecuteScalar("SELECT COUNT(1) FROM child").ShouldBe(0); @@ -224,14 +224,14 @@ public async Task ShouldHandleComplexCycles() _database.ExecuteScalar("SELECT COUNT(1) FROM e").ShouldBe(1); _database.ExecuteScalar("SELECT COUNT(1) FROM f").ShouldBe(1); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql, SchemasToInclude = new[] { "MySqlTests" } - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -258,13 +258,13 @@ public async Task ShouldIgnoreTables() _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Bar { Value = i })); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql, TablesToIgnore = new Table[] { "Foo" }, SchemasToInclude = new[] { "MySqlTests" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM Foo").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM Bar").ShouldBe(0); @@ -281,13 +281,13 @@ public async Task ShouldIncludeTables() _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Bar { Value = i })); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql, TablesToInclude = new Table[] { "Foo" }, SchemasToInclude = new[] { "MySqlTests" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM Foo").ShouldBe(0); _database.ExecuteScalar("SELECT COUNT(1) FROM Bar").ShouldBe(100); @@ -311,12 +311,12 @@ public async Task ShouldExcludeSchemas() _database.Execute("INSERT `B`.`Bar` VALUES (" + i + ")"); } - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql, SchemasToExclude = new[] { "A", "MySqlTests" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM A.Foo").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM B.Bar").ShouldBe(0); @@ -340,12 +340,12 @@ public async Task ShouldIncludeSchemas() _database.Execute("INSERT B.Bar VALUES (" + i + ")"); } - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql, SchemasToInclude = new[] { "B" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM A.Foo").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM B.Bar").ShouldBe(0); @@ -359,13 +359,13 @@ public async Task ShouldResetSequencesAndIdentities() _database.Execute("INSERT INTO a(id) VALUES (0)"); _database.Execute("INSERT INTO a(id) VALUES (0)"); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql, WithReseed = true - }; + }); - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'MySqlTests' AND TABLE_NAME = 'a';").ShouldBe(1); } diff --git a/Respawn.DatabaseTests/PostgresTests.cs b/Respawn.DatabaseTests/PostgresTests.cs index 79cfaf3..992172b 100644 --- a/Respawn.DatabaseTests/PostgresTests.cs +++ b/Respawn.DatabaseTests/PostgresTests.cs @@ -65,11 +65,11 @@ public async Task ShouldDeleteData() _database.ExecuteScalar("SELECT COUNT(1) FROM \"foo\"").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM \"foo\"").ShouldBe(0); } @@ -86,12 +86,12 @@ public async Task ShouldIgnoreTables() await _database.ExecuteAsync("INSERT INTO \"bar\" VALUES (@0)", i); } - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres, TablesToIgnore = new Table[] { "foo" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM foo").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM bar").ShouldBe(0); @@ -109,12 +109,12 @@ public async Task ShouldIncludeTables() await _database.ExecuteAsync("INSERT INTO \"bar\" VALUES (@0)", i); } - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres, TablesToInclude = new Table[] { "foo" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM foo").ShouldBe(0); _database.ExecuteScalar("SELECT COUNT(1) FROM bar").ShouldBe(100); @@ -135,14 +135,14 @@ public async Task ShouldHandleRelationships() _database.ExecuteScalar("SELECT COUNT(1) FROM foo").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM baz").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres, SchemasToInclude = new [] { "public" } - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -174,13 +174,13 @@ public async Task ShouldHandleCircularRelationships() _database.ExecuteScalar("SELECT COUNT(1) FROM parent").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM child").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -206,13 +206,13 @@ public async Task ShouldHandleSelfRelationships() _database.ExecuteScalar("SELECT COUNT(1) FROM foo").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -257,13 +257,13 @@ public async Task ShouldHandleComplexCycles() _database.ExecuteScalar("SELECT COUNT(1) FROM e").ShouldBe(1); _database.ExecuteScalar("SELECT COUNT(1) FROM f").ShouldBe(1); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -294,12 +294,12 @@ public async Task ShouldExcludeSchemas() await _database.ExecuteAsync("INSERT INTO b.bar VALUES (" + i + ")"); } - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres, SchemasToExclude = new [] { "a" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM a.foo").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM b.bar").ShouldBe(0); @@ -319,12 +319,12 @@ public async Task ShouldIncludeSchemas() await _database.ExecuteAsync("INSERT INTO b.bar VALUES (" + i + ")"); } - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres, SchemasToInclude = new [] { "b" } - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM a.foo").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM b.bar").ShouldBe(0); @@ -338,13 +338,13 @@ public async Task ShouldResetSequencesAndIdentities() await _database.ExecuteAsync("INSERT INTO a DEFAULT VALUES"); await _database.ExecuteAsync("INSERT INTO a DEFAULT VALUES"); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres, WithReseed = true - }; + }); - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT nextval('a_id_seq')").ShouldBe(1); _database.ExecuteScalar("SELECT nextval('a_value_seq')").ShouldBe(1); } diff --git a/Respawn.DatabaseTests/SqlServerTests.cs b/Respawn.DatabaseTests/SqlServerTests.cs index 7b0ff0e..6a41fc1 100644 --- a/Respawn.DatabaseTests/SqlServerTests.cs +++ b/Respawn.DatabaseTests/SqlServerTests.cs @@ -87,10 +87,10 @@ public async Task ShouldDeleteData() _database.ExecuteScalar("SELECT COUNT(1) FROM Foo").ShouldBe(100); - var checkpoint = new Checkpoint(); + var checkpoint = await Respawner.CreateAsync(_connection); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -113,10 +113,10 @@ public async Task ShouldHandleRelationships() _database.ExecuteScalar("SELECT COUNT(1) FROM Foo").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM Baz").ShouldBe(100); - var checkpoint = new Checkpoint(); + var checkpoint = await Respawner.CreateAsync(_connection); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -142,10 +142,10 @@ public async Task ShouldHandleSelfRelationships() _database.ExecuteScalar("SELECT COUNT(1) FROM circle").ShouldBe(100); - var checkpoint = new Checkpoint(); + var checkpoint = await Respawner.CreateAsync(_connection); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -190,10 +190,10 @@ public async Task ShouldHandleComplexCycles() _database.ExecuteScalar("SELECT COUNT(1) FROM e").ShouldBe(1); _database.ExecuteScalar("SELECT COUNT(1) FROM f").ShouldBe(1); - var checkpoint = new Checkpoint(); + var checkpoint = await Respawner.CreateAsync(_connection); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -226,10 +226,10 @@ public async Task ShouldHandleCircularRelationships() _database.ExecuteScalar("SELECT COUNT(1) FROM Parent").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM Child").ShouldBe(100); - var checkpoint = new Checkpoint(); + var checkpoint = await Respawner.CreateAsync(_connection); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -250,13 +250,13 @@ public async Task ShouldIgnoreTables() await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Bar { Value = i })); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { TablesToIgnore = new Table[] { "Foo" } - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -289,17 +289,17 @@ public async Task ShouldIgnoreTablesWithSchema() await _database.ExecuteAsync("INSERT B.Foo VALUES (" + i + ")"); } - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { TablesToIgnore = new[] { new Table("A", "Foo"), new Table("A", "FooWithBrackets") } - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -322,13 +322,13 @@ public async Task ShouldIncludeTables() await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Bar { Value = i })); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { TablesToInclude = new Table[] { "Foo" } - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -356,13 +356,13 @@ public async Task ShouldExcludeSchemas() await _database.ExecuteAsync("INSERT B.Bar VALUES (" + i + ")"); } - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { SchemasToExclude = new[] { "A" } - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -390,13 +390,13 @@ public async Task ShouldIncludeSchemas() await _database.ExecuteAsync("INSERT B.Bar VALUES (" + i + ")"); } - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { SchemasToInclude = new[] { "B" } - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -417,13 +417,13 @@ public async Task ShouldReseedId() _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { WithReseed = true - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -449,13 +449,13 @@ public async Task ShouldReseedId_TableWithSchema() _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { WithReseed = true - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -474,13 +474,13 @@ public async Task ShouldReseedId_TableHasNeverHadAnyData() await _database.ExecuteAsync("drop schema if exists A"); await _database.ExecuteAsync("create schema A"); await _database.ExecuteAsync("create table A.Foo ([id] [int] IDENTITY(1,1), Value int)"); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { WithReseed = true - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -496,13 +496,13 @@ public async Task ShouldReseedId_TableHasNeverHadAnyData() public async Task ShouldReseedId_TableWithSchemaHasNeverHadAnyData() { await _database.ExecuteAsync("create table Foo ([id] [int] IDENTITY(1,1), Value int)"); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { WithReseed = true - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -523,13 +523,13 @@ public async Task ShouldNotReseedId() _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { WithReseed = false - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -555,13 +555,13 @@ public async Task ShouldNotReseedId_TableWithSchema() _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { WithReseed = false - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -582,14 +582,14 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue() _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(1100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { WithReseed = true - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -615,14 +615,14 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSch _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1100); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { WithReseed = true - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -639,14 +639,14 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableHasNeve { await _database.ExecuteAsync("create table Foo ([id] [int] IDENTITY(1001,1), Value int)"); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { WithReseed = true - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -665,14 +665,14 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSch await _database.ExecuteAsync("create schema A"); await _database.ExecuteAsync("create table A.Foo ([id] [int] IDENTITY(1001,1), Value int)"); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { WithReseed = true - }; + }); try { - await checkpoint.Reset(_connection); + await checkpoint.ResetAsync(_connection); } catch { @@ -700,11 +700,11 @@ await _database.ExecuteAsync("create table Foo (Value [int] not null primary key await _database.ExecuteAsync("INSERT Foo (Value) VALUES (1)"); await _database.ExecuteAsync("UPDATE Foo SET Value = 2 Where Value = 1"); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { CheckTemporalTables = true - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM FooHistory").ShouldBe(0); } @@ -725,11 +725,11 @@ await _database.ExecuteAsync("create table Foo (Value [int] not null primary key await _database.ExecuteAsync("INSERT Foo (Value) VALUES (1)"); await _database.ExecuteAsync("UPDATE Foo SET Value = 2 Where Value = 1"); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { CheckTemporalTables = true - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); var sql = @" SELECT t1.name @@ -755,11 +755,11 @@ await _database.ExecuteAsync("create table Foo (Value [int] not null primary key await _database.ExecuteAsync("INSERT Foo (Value) VALUES (1)"); await _database.ExecuteAsync("UPDATE Foo SET Value = 2 Where Value = 1"); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { CheckTemporalTables = true - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); var sql = @" SELECT t1.name @@ -784,11 +784,11 @@ await _database.ExecuteAsync("create table TableSchema.Foo (Value [int] not null await _database.ExecuteAsync("INSERT TableSchema.Foo (Value) VALUES (1)"); await _database.ExecuteAsync("UPDATE TableSchema.Foo SET Value = 2 Where Value = 1"); - var checkpoint = new Checkpoint + var checkpoint = await Respawner.CreateAsync(_connection, new RespawnerOptions { CheckTemporalTables = true - }; - await checkpoint.Reset(_connection); + }); + await checkpoint.ResetAsync(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM HistorySchema.FooHistory").ShouldBe(0); } diff --git a/Respawn.sln b/Respawn.sln index 3a3685c..b477839 100644 --- a/Respawn.sln +++ b/Respawn.sln @@ -17,6 +17,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution informix-server\my_post.sh = informix-server\my_post.sh informix-server\onconfig = informix-server\onconfig Push.ps1 = Push.ps1 + README.md = README.md .github\workflows\release.yml = .github\workflows\release.yml EndProjectSection EndProject diff --git a/Respawn/IDbAdapter.cs b/Respawn/IDbAdapter.cs index 86b8474..5f3c7e3 100644 --- a/Respawn/IDbAdapter.cs +++ b/Respawn/IDbAdapter.cs @@ -7,9 +7,9 @@ namespace Respawn { public interface IDbAdapter { - string BuildTableCommandText(Checkpoint checkpoint); - string BuildTemporalTableCommandText(Checkpoint checkpoint); - string BuildRelationshipCommandText(Checkpoint checkpoint); + string BuildTableCommandText(RespawnerOptions options); + string BuildTemporalTableCommandText(RespawnerOptions options); + string BuildRelationshipCommandText(RespawnerOptions options); string BuildDeleteCommandText(GraphBuilder builder); string BuildReseedSql(IEnumerable tablesToDelete); string BuildTurnOffSystemVersioningCommandText(IEnumerable tablesToTurnOffSystemVersioning); diff --git a/Respawn/InformixDbAdapter.cs b/Respawn/InformixDbAdapter.cs index 7bd93a6..b84c9a9 100644 --- a/Respawn/InformixDbAdapter.cs +++ b/Respawn/InformixDbAdapter.cs @@ -11,16 +11,16 @@ internal class InformixDbAdapter : IDbAdapter { private const char QuoteCharacter = '"'; - public string BuildTableCommandText(Checkpoint checkpoint) + public string BuildTableCommandText(RespawnerOptions options) { string commandText = @"SELECT t.owner, t.tabname FROM 'informix'.systables t WHERE t.tabtype = 'T' AND t.tabid >= 100"; - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, @@ -46,9 +46,9 @@ public string BuildTableCommandText(Checkpoint checkpoint) } } } - if (checkpoint.TablesToInclude.Any()) + if (options.TablesToInclude.Any()) { - var tablesToIncludeGroups = checkpoint.TablesToInclude + var tablesToIncludeGroups = options.TablesToInclude .GroupBy( t => t.Schema != null, t => t, @@ -75,15 +75,15 @@ public string BuildTableCommandText(Checkpoint checkpoint) } } - if (checkpoint.SchemasToExclude.Any()) + if (options.SchemasToExclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToExclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToExclude.Select(t => $"'{t}'")); commandText += " AND t.owner NOT IN (" + args + ")"; } - else if (checkpoint.SchemasToInclude.Any()) + else if (options.SchemasToInclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToInclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToInclude.Select(t => $"'{t}'")); commandText += " AND t.owner IN (" + args + ")"; } @@ -91,7 +91,7 @@ public string BuildTableCommandText(Checkpoint checkpoint) return commandText; } - public string BuildRelationshipCommandText(Checkpoint checkpoint) + public string BuildRelationshipCommandText(RespawnerOptions options) { string commandText = @"SELECT T2.owner, T2.tabname, T1.owner, T1.tabname, C.constrname FROM sysreferences R @@ -105,9 +105,9 @@ INNER JOIN systables T2 AND (T1.tabtype = 'T' AND T1.tabid >= 100) AND (T2.tabtype = 'T' AND T2.tabid >= 100)"; - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, @@ -133,9 +133,9 @@ INNER JOIN systables T2 } } } - if (checkpoint.TablesToInclude.Any()) + if (options.TablesToInclude.Any()) { - var tablesToIncludeGroups = checkpoint.TablesToInclude + var tablesToIncludeGroups = options.TablesToInclude .GroupBy( t => t.Schema != null, t => t, @@ -161,15 +161,15 @@ INNER JOIN systables T2 } } } - if (checkpoint.SchemasToExclude.Any()) + if (options.SchemasToExclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToExclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToExclude.Select(t => $"'{t}'")); commandText += " AND T2.owner NOT IN (" + args + ")"; } - else if (checkpoint.SchemasToInclude.Any()) + else if (options.SchemasToInclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToInclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToInclude.Select(t => $"'{t}'")); commandText += " AND T2.owner IN (" + args + ")"; } @@ -199,7 +199,7 @@ public string BuildDeleteCommandText(GraphBuilder graph) public string BuildReseedSql(IEnumerable
tablesToDelete) => throw new System.NotImplementedException(); - public string BuildTemporalTableCommandText(Checkpoint checkpoint) => throw new System.NotImplementedException(); + public string BuildTemporalTableCommandText(RespawnerOptions options) => throw new System.NotImplementedException(); public string BuildTurnOffSystemVersioningCommandText(IEnumerable tablesToTurnOffSystemVersioning) => throw new System.NotImplementedException(); diff --git a/Respawn/MySqlAdapter.cs b/Respawn/MySqlAdapter.cs index 4962841..16a244e 100644 --- a/Respawn/MySqlAdapter.cs +++ b/Respawn/MySqlAdapter.cs @@ -11,7 +11,7 @@ internal class MySqlAdapter : IDbAdapter { private const char QuoteCharacter = '`'; - public string BuildTableCommandText(Checkpoint checkpoint) + public string BuildTableCommandText(RespawnerOptions options) { string commandText = @" SELECT t.TABLE_SCHEMA, t.TABLE_NAME @@ -21,9 +21,9 @@ information_schema.tables AS t table_type = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('mysql' , 'performance_schema')"; - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, @@ -49,9 +49,9 @@ information_schema.tables AS t } } } - if (checkpoint.TablesToInclude.Any()) + if (options.TablesToInclude.Any()) { - var tablesToIncludeGroups = checkpoint.TablesToInclude + var tablesToIncludeGroups = options.TablesToInclude .GroupBy( t => t.Schema != null, t => t, @@ -77,15 +77,15 @@ information_schema.tables AS t } } } - if (checkpoint.SchemasToExclude.Any()) + if (options.SchemasToExclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToExclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToExclude.Select(t => $"'{t}'")); commandText += " AND t.TABLE_SCHEMA NOT IN (" + args + ")"; } - else if (checkpoint.SchemasToInclude.Any()) + else if (options.SchemasToInclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToInclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToInclude.Select(t => $"'{t}'")); commandText += " AND t.TABLE_SCHEMA IN (" + args + ")"; } @@ -93,7 +93,7 @@ information_schema.tables AS t return commandText; } - public string BuildRelationshipCommandText(Checkpoint checkpoint) + public string BuildRelationshipCommandText(RespawnerOptions options) { var commandText = @" SELECT @@ -106,9 +106,9 @@ public string BuildRelationshipCommandText(Checkpoint checkpoint) var whereText = new List(); - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, @@ -134,9 +134,9 @@ public string BuildRelationshipCommandText(Checkpoint checkpoint) } } } - if (checkpoint.TablesToInclude.Any()) + if (options.TablesToInclude.Any()) { - var tablesToIncludeGroups = checkpoint.TablesToInclude + var tablesToIncludeGroups = options.TablesToInclude .GroupBy( t => t.Schema != null, t => t, @@ -162,14 +162,14 @@ public string BuildRelationshipCommandText(Checkpoint checkpoint) } } } - if (checkpoint.SchemasToExclude.Any()) + if (options.SchemasToExclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToExclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToExclude.Select(t => $"'{t}'")); whereText.Add("CONSTRAINT_SCHEMA NOT IN (" + args + ")"); } - else if (checkpoint.SchemasToInclude.Any()) + else if (options.SchemasToInclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToInclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToInclude.Select(t => $"'{t}'")); whereText.Add("CONSTRAINT_SCHEMA IN (" + args + ")"); } @@ -203,7 +203,7 @@ public string BuildReseedSql(IEnumerable
tablesToDelete) return builder.ToString(); } - public string BuildTemporalTableCommandText(Checkpoint checkpoint) => throw new System.NotImplementedException(); + public string BuildTemporalTableCommandText(RespawnerOptions options) => throw new System.NotImplementedException(); public string BuildTurnOffSystemVersioningCommandText(IEnumerable tablesToTurnOffSystemVersioning) => throw new System.NotImplementedException(); diff --git a/Respawn/OracleDbAdapter.cs b/Respawn/OracleDbAdapter.cs index 241106e..3b6dbfd 100644 --- a/Respawn/OracleDbAdapter.cs +++ b/Respawn/OracleDbAdapter.cs @@ -10,7 +10,7 @@ internal class OracleDbAdapter : IDbAdapter { private const char QuoteCharacter = '"'; - public string BuildTableCommandText(Checkpoint checkpoint) + public string BuildTableCommandText(RespawnerOptions options) { string commandText = @" select OWNER, TABLE_NAME @@ -18,9 +18,9 @@ from ALL_TABLES where 1=1 " ; - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, @@ -46,9 +46,9 @@ from ALL_TABLES } } } - if (checkpoint.TablesToInclude.Any()) + if (options.TablesToInclude.Any()) { - var tablesToIncludeGroups = checkpoint.TablesToInclude + var tablesToIncludeGroups = options.TablesToInclude .GroupBy( t => t.Schema != null, t => t, @@ -74,15 +74,15 @@ from ALL_TABLES } } } - if (checkpoint.SchemasToExclude.Any()) + if (options.SchemasToExclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToExclude.Select(schema => $"'{schema}'").ToArray()); + var args = string.Join(",", options.SchemasToExclude.Select(schema => $"'{schema}'").ToArray()); commandText += " AND OWNER NOT IN (" + args + ")"; } - else if (checkpoint.SchemasToInclude.Any()) + else if (options.SchemasToInclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToInclude.Select(schema => $"'{schema}'").ToArray()); + var args = string.Join(",", options.SchemasToInclude.Select(schema => $"'{schema}'").ToArray()); commandText += " AND OWNER IN (" + args + ")"; } @@ -90,7 +90,7 @@ from ALL_TABLES return commandText; } - public string BuildRelationshipCommandText(Checkpoint checkpoint) + public string BuildRelationshipCommandText(RespawnerOptions options) { string commandText = @" select a.owner as table_schema,a.table_name, b.owner as table_schema ,b.table_name, a.constraint_name @@ -98,9 +98,9 @@ from all_CONSTRAINTS a inner join all_CONSTRAINTS b on a.r_constraint_name=b.constraint_name AND a.r_owner=b.owner where a.constraint_type in ('P','R')"; - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, @@ -126,9 +126,9 @@ from all_CONSTRAINTS a } } } - if (checkpoint.TablesToInclude.Any()) + if (options.TablesToInclude.Any()) { - var tablesToIncludeGroups = checkpoint.TablesToInclude + var tablesToIncludeGroups = options.TablesToInclude .GroupBy( t => t.Schema != null, t => t, @@ -154,15 +154,15 @@ from all_CONSTRAINTS a } } } - if (checkpoint.SchemasToExclude.Any()) + if (options.SchemasToExclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToExclude.Select(s => $"'{s}'").ToArray()); + var args = string.Join(",", options.SchemasToExclude.Select(s => $"'{s}'").ToArray()); commandText += " AND a.OWNER NOT IN (" + args + ")"; } - else if (checkpoint.SchemasToInclude.Any()) + else if (options.SchemasToInclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToInclude.Select(s => $"'{s}'").ToArray()); + var args = string.Join(",", options.SchemasToInclude.Select(s => $"'{s}'").ToArray()); commandText += " AND a.OWNER IN (" + args + ")"; } @@ -193,7 +193,7 @@ private static IEnumerable BuildCommands(GraphBuilder graph) } public string BuildReseedSql(IEnumerable
tablesToDelete) => throw new System.NotImplementedException(); - public string BuildTemporalTableCommandText(Checkpoint checkpoint) => throw new System.NotImplementedException(); + public string BuildTemporalTableCommandText(RespawnerOptions options) => throw new System.NotImplementedException(); public string BuildTurnOffSystemVersioningCommandText(IEnumerable tablesToTurnOffSystemVersioning) => throw new System.NotImplementedException(); diff --git a/Respawn/PostgresDbAdapter.cs b/Respawn/PostgresDbAdapter.cs index cb30965..8e570aa 100644 --- a/Respawn/PostgresDbAdapter.cs +++ b/Respawn/PostgresDbAdapter.cs @@ -15,7 +15,7 @@ internal class PostgresDbAdapter : IDbAdapter private const string InformationSchema = "information_schema"; private const string PostgresSchemaPrefix = "pg_"; - public string BuildTableCommandText(Checkpoint checkpoint) + public string BuildTableCommandText(RespawnerOptions options) { string commandText = @" select TABLE_SCHEMA, TABLE_NAME @@ -23,9 +23,9 @@ from INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'" ; - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, @@ -51,9 +51,9 @@ from INFORMATION_SCHEMA.TABLES } } } - if (checkpoint.TablesToInclude.Any()) + if (options.TablesToInclude.Any()) { - var tablesToIncludeGroups = checkpoint.TablesToInclude + var tablesToIncludeGroups = options.TablesToInclude .GroupBy( t => t.Schema != null, t => t, @@ -79,17 +79,17 @@ from INFORMATION_SCHEMA.TABLES } } } - if (checkpoint.SchemasToExclude.Any()) + if (options.SchemasToExclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToExclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToExclude.Select(t => $"'{t}'")); args += $", '{InformationSchema}'"; commandText += " AND TABLE_SCHEMA NOT IN (" + args + ")"; commandText += $" AND TABLE_SCHEMA NOT LIKE '{PostgresSchemaPrefix}%'"; } - else if (checkpoint.SchemasToInclude.Any()) + else if (options.SchemasToInclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToInclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToInclude.Select(t => $"'{t}'")); commandText += " AND TABLE_SCHEMA IN (" + args + ")"; } @@ -102,7 +102,7 @@ from INFORMATION_SCHEMA.TABLES return commandText; } - public string BuildRelationshipCommandText(Checkpoint checkpoint) + public string BuildRelationshipCommandText(RespawnerOptions options) { string commandText = @" select tc.table_schema, tc.table_name, ctu.table_schema, ctu.table_name, rc.constraint_name @@ -111,9 +111,9 @@ from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc inner join INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc ON rc.constraint_name = tc.constraint_name where 1=1"; - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, @@ -139,9 +139,9 @@ from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc } } } - if (checkpoint.TablesToInclude.Any()) + if (options.TablesToInclude.Any()) { - var tablesToIncludeGroups = checkpoint.TablesToInclude + var tablesToIncludeGroups = options.TablesToInclude .GroupBy( t => t.Schema != null, t => t, @@ -167,15 +167,15 @@ from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc } } } - if (checkpoint.SchemasToExclude.Any()) + if (options.SchemasToExclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToExclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToExclude.Select(t => $"'{t}'")); commandText += " AND tc.TABLE_SCHEMA NOT IN (" + args + ")"; } - else if (checkpoint.SchemasToInclude.Any()) + else if (options.SchemasToInclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToInclude.Select(t => $"'{t}'")); + var args = string.Join(",", options.SchemasToInclude.Select(t => $"'{t}'")); commandText += " AND tc.TABLE_SCHEMA IN (" + args + ")"; } @@ -234,7 +234,7 @@ WHERE pg_get_serial_sequence(quote_ident(table_schema) || '.' || quote_ident(tab SELECT pg_temp.reset_sequence(s.sequence_name) FROM all_sequences s;"; } - public string BuildTemporalTableCommandText(Checkpoint checkpoint) => throw new System.NotImplementedException(); + public string BuildTemporalTableCommandText(RespawnerOptions options) => throw new System.NotImplementedException(); public string BuildTurnOffSystemVersioningCommandText(IEnumerable tablesToTurnOffSystemVersioning) => throw new System.NotImplementedException(); diff --git a/Respawn/Respawn.csproj b/Respawn/Respawn.csproj index 8962539..a976ef3 100644 --- a/Respawn/Respawn.csproj +++ b/Respawn/Respawn.csproj @@ -1,7 +1,7 @@  - Intelligent checkpoints for database tests + Intelligent resetting for database tests Copyright Jimmy Bogard Jimmy Bogard netstandard2.1 diff --git a/Respawn/Checkpoint.cs b/Respawn/Respawner.cs similarity index 67% rename from Respawn/Checkpoint.cs rename to Respawn/Respawner.cs index 3b23ba0..fb473b7 100644 --- a/Respawn/Checkpoint.cs +++ b/Respawn/Respawner.cs @@ -1,176 +1,194 @@ -using System; -using System.Collections.Generic; -using System.Data.Common; -using Microsoft.Data.SqlClient; -using System.Linq; -using System.Threading.Tasks; -using Respawn.Graph; - -namespace Respawn -{ - public class Checkpoint - { - private IList _temporalTables = new List(); - - public Table[] TablesToIgnore { get; init; } = Array.Empty
(); - public Table[] TablesToInclude { get; init; } = Array.Empty
(); - public string[] SchemasToInclude { get; init; } = Array.Empty(); - public string[] SchemasToExclude { get; init; } = Array.Empty(); - public string? DeleteSql { get; private set; } - public string? ReseedSql { get; private set; } - public bool CheckTemporalTables { get; init; } - public bool WithReseed { get; init; } - public IDbAdapter DbAdapter { get; init; } = Respawn.DbAdapter.SqlServer; - - public int? CommandTimeout { get; init; } - - public virtual async Task Reset(string nameOrConnectionString) - { - await using var connection = new SqlConnection(nameOrConnectionString); - - await connection.OpenAsync(); - - await Reset(connection); - } - - public virtual async Task Reset(DbConnection connection) - { - if (string.IsNullOrWhiteSpace(DeleteSql)) - { - await BuildDeleteTables(connection); - } - - if (_temporalTables.Any()) - { - var turnOffVersioningCommandText = DbAdapter.BuildTurnOffSystemVersioningCommandText(_temporalTables); - await ExecuteAlterSystemVersioningAsync(connection, turnOffVersioningCommandText); - } - - try - { - await ExecuteDeleteSqlAsync(connection); - } - finally - { - if (_temporalTables.Any()) - { - var turnOnVersioningCommandText = DbAdapter.BuildTurnOnSystemVersioningCommandText(_temporalTables); - await ExecuteAlterSystemVersioningAsync(connection, turnOnVersioningCommandText); - } - } - } - - private async Task ExecuteAlterSystemVersioningAsync(DbConnection connection, string commandText) - { - await using var tx = await connection.BeginTransactionAsync(); - await using var cmd = connection.CreateCommand(); - - cmd.CommandTimeout = CommandTimeout ?? cmd.CommandTimeout; - cmd.CommandText = commandText; - cmd.Transaction = tx; - - await cmd.ExecuteNonQueryAsync(); - - await tx.CommitAsync(); - } - - private async Task ExecuteDeleteSqlAsync(DbConnection connection) - { - await using var tx = await connection.BeginTransactionAsync(); - await using var cmd = connection.CreateCommand(); - - cmd.CommandTimeout = CommandTimeout ?? cmd.CommandTimeout; - cmd.CommandText = DeleteSql; - cmd.Transaction = tx; - - await cmd.ExecuteNonQueryAsync(); - - if (ReseedSql != null) - { - cmd.CommandText = ReseedSql; - await cmd.ExecuteNonQueryAsync(); - } - - await tx.CommitAsync(); - } - - private async Task BuildDeleteTables(DbConnection connection) - { - var allTables = await GetAllTables(connection); - - if (CheckTemporalTables && await DbAdapter.CheckSupportsTemporalTables(connection)) - { - _temporalTables = await GetAllTemporalTables(connection); - } - - var allRelationships = await GetRelationships(connection); - - var graphBuilder = new GraphBuilder(allTables, allRelationships); - - DeleteSql = DbAdapter.BuildDeleteCommandText(graphBuilder); - ReseedSql = WithReseed ? DbAdapter.BuildReseedSql(graphBuilder.ToDelete) : null; - } - - private async Task> GetRelationships(DbConnection connection) - { - var relationships = new HashSet(); - var commandText = DbAdapter.BuildRelationshipCommandText(this); - - await using var cmd = connection.CreateCommand(); - - cmd.CommandText = commandText; - - await using var reader = await cmd.ExecuteReaderAsync(); - - while (await reader.ReadAsync()) - { - relationships.Add(new Relationship( - new Table(await reader.IsDBNullAsync(0) ? null : reader.GetString(0), reader.GetString(1)), - new Table(await reader.IsDBNullAsync(2) ? null : reader.GetString(2), reader.GetString(3)), - reader.GetString(4))); - } - - return relationships; - } - - private async Task> GetAllTables(DbConnection connection) - { - var tables = new HashSet
(); - - var commandText = DbAdapter.BuildTableCommandText(this); - - await using var cmd = connection.CreateCommand(); - - cmd.CommandText = commandText; - - await using var reader = await cmd.ExecuteReaderAsync(); - - while (await reader.ReadAsync()) - { - tables.Add(new Table(await reader.IsDBNullAsync(0) ? null : reader.GetString(0), reader.GetString(1))); - } - - return tables; - } - - private async Task> GetAllTemporalTables(DbConnection connection) - { - var tables = new List(); - - var commandText = DbAdapter.BuildTemporalTableCommandText(this); - - await using var cmd = connection.CreateCommand(); - - cmd.CommandText = commandText; - - await using var reader = await cmd.ExecuteReaderAsync(); - - while (await reader.ReadAsync()) - { - tables.Add(new TemporalTable(await reader.IsDBNullAsync(0) ? null : reader.GetString(0), reader.GetString(1), reader.GetString(2), reader.GetString(3))); - } - - return tables; - } - } -} +using System; +using System.Collections.Generic; +using System.Data.Common; +using Microsoft.Data.SqlClient; +using System.Linq; +using System.Threading.Tasks; +using Respawn.Graph; + +namespace Respawn +{ + public class Respawner + { + private IList _temporalTables = new List(); + public RespawnerOptions Options { get; } + public string? DeleteSql { get; private set; } + public string? ReseedSql { get; private set; } + + private Respawner(RespawnerOptions options) + { + Options = options; + } + + public static async Task CreateAsync(string nameOrConnectionString, RespawnerOptions? options = default) + { + options ??= new RespawnerOptions(); + + await using var connection = new SqlConnection(nameOrConnectionString); + + await connection.OpenAsync(); + + var respawner = new Respawner(options); + + await respawner.BuildDeleteTables(connection); + + return respawner; + } + + public static async Task CreateAsync(DbConnection connection, RespawnerOptions? options = default) + { + options ??= new RespawnerOptions(); + + var respawner = new Respawner(options); + + await respawner.BuildDeleteTables(connection); + + return respawner; + } + + + public virtual async Task ResetAsync(string nameOrConnectionString) + { + await using var connection = new SqlConnection(nameOrConnectionString); + + await connection.OpenAsync(); + + await ResetAsync(connection); + } + + public virtual async Task ResetAsync(DbConnection connection) + { + if (_temporalTables.Any()) + { + var turnOffVersioningCommandText = Options.DbAdapter.BuildTurnOffSystemVersioningCommandText(_temporalTables); + await ExecuteAlterSystemVersioningAsync(connection, turnOffVersioningCommandText); + } + + try + { + await ExecuteDeleteSqlAsync(connection); + } + finally + { + if (_temporalTables.Any()) + { + var turnOnVersioningCommandText = Options.DbAdapter.BuildTurnOnSystemVersioningCommandText(_temporalTables); + await ExecuteAlterSystemVersioningAsync(connection, turnOnVersioningCommandText); + } + } + } + + private async Task ExecuteAlterSystemVersioningAsync(DbConnection connection, string commandText) + { + await using var tx = await connection.BeginTransactionAsync(); + await using var cmd = connection.CreateCommand(); + + cmd.CommandTimeout = Options.CommandTimeout ?? cmd.CommandTimeout; + cmd.CommandText = commandText; + cmd.Transaction = tx; + + await cmd.ExecuteNonQueryAsync(); + + await tx.CommitAsync(); + } + + private async Task ExecuteDeleteSqlAsync(DbConnection connection) + { + await using var tx = await connection.BeginTransactionAsync(); + await using var cmd = connection.CreateCommand(); + + cmd.CommandTimeout = Options.CommandTimeout ?? cmd.CommandTimeout; + cmd.CommandText = DeleteSql; + cmd.Transaction = tx; + + await cmd.ExecuteNonQueryAsync(); + + if (ReseedSql != null) + { + cmd.CommandText = ReseedSql; + await cmd.ExecuteNonQueryAsync(); + } + + await tx.CommitAsync(); + } + + private async Task BuildDeleteTables(DbConnection connection) + { + var allTables = await GetAllTables(connection); + + if (Options.CheckTemporalTables && await Options.DbAdapter.CheckSupportsTemporalTables(connection)) + { + _temporalTables = await GetAllTemporalTables(connection); + } + + var allRelationships = await GetRelationships(connection); + + var graphBuilder = new GraphBuilder(allTables, allRelationships); + + DeleteSql = Options.DbAdapter.BuildDeleteCommandText(graphBuilder); + ReseedSql = Options.WithReseed ? Options.DbAdapter.BuildReseedSql(graphBuilder.ToDelete) : null; + } + + private async Task> GetRelationships(DbConnection connection) + { + var relationships = new HashSet(); + var commandText = Options.DbAdapter.BuildRelationshipCommandText(Options); + + await using var cmd = connection.CreateCommand(); + + cmd.CommandText = commandText; + + await using var reader = await cmd.ExecuteReaderAsync(); + + while (await reader.ReadAsync()) + { + relationships.Add(new Relationship( + new Table(await reader.IsDBNullAsync(0) ? null : reader.GetString(0), reader.GetString(1)), + new Table(await reader.IsDBNullAsync(2) ? null : reader.GetString(2), reader.GetString(3)), + reader.GetString(4))); + } + + return relationships; + } + + private async Task> GetAllTables(DbConnection connection) + { + var tables = new HashSet
(); + + var commandText = Options.DbAdapter.BuildTableCommandText(Options); + + await using var cmd = connection.CreateCommand(); + + cmd.CommandText = commandText; + + await using var reader = await cmd.ExecuteReaderAsync(); + + while (await reader.ReadAsync()) + { + tables.Add(new Table(await reader.IsDBNullAsync(0) ? null : reader.GetString(0), reader.GetString(1))); + } + + return tables; + } + + private async Task> GetAllTemporalTables(DbConnection connection) + { + var tables = new List(); + + var commandText = Options.DbAdapter.BuildTemporalTableCommandText(Options); + + await using var cmd = connection.CreateCommand(); + + cmd.CommandText = commandText; + + await using var reader = await cmd.ExecuteReaderAsync(); + + while (await reader.ReadAsync()) + { + tables.Add(new TemporalTable(await reader.IsDBNullAsync(0) ? null : reader.GetString(0), reader.GetString(1), reader.GetString(2), reader.GetString(3))); + } + + return tables; + } + } +} diff --git a/Respawn/RespawnerOptions.cs b/Respawn/RespawnerOptions.cs new file mode 100644 index 0000000..7eb762f --- /dev/null +++ b/Respawn/RespawnerOptions.cs @@ -0,0 +1,17 @@ +using Respawn.Graph; +using System; + +namespace Respawn; + +public class RespawnerOptions +{ + public Table[] TablesToIgnore { get; init; } = Array.Empty
(); + public Table[] TablesToInclude { get; init; } = Array.Empty
(); + public string[] SchemasToInclude { get; init; } = Array.Empty(); + public string[] SchemasToExclude { get; init; } = Array.Empty(); + public bool CheckTemporalTables { get; init; } + public bool WithReseed { get; init; } + public int? CommandTimeout { get; init; } + public IDbAdapter DbAdapter { get; init; } = Respawn.DbAdapter.SqlServer; + +} \ No newline at end of file diff --git a/Respawn/SqlServerDbAdapter.cs b/Respawn/SqlServerDbAdapter.cs index 89ebbb7..cd7a930 100644 --- a/Respawn/SqlServerDbAdapter.cs +++ b/Respawn/SqlServerDbAdapter.cs @@ -15,7 +15,7 @@ internal class SqlServerDbAdapter : IDbAdapter private byte? _compatibilityLevel; private int? _engineEdition; - public string BuildTableCommandText(Checkpoint checkpoint) + public string BuildTableCommandText(RespawnerOptions options) { string commandText = @" select s.name, t.name @@ -23,9 +23,9 @@ from sys.tables t INNER JOIN sys.schemas s ON t.schema_id = s.schema_id WHERE 1=1"; - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, @@ -50,9 +50,9 @@ from sys.tables t } } } - if (checkpoint.TablesToInclude.Any()) + if (options.TablesToInclude.Any()) { - var tablesToIncludeGroups = checkpoint.TablesToInclude + var tablesToIncludeGroups = options.TablesToInclude .GroupBy( t => t.Schema != null, t => t, @@ -78,15 +78,15 @@ from sys.tables t } } } - if (checkpoint.SchemasToExclude.Any()) + if (options.SchemasToExclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToExclude.Select(schema => $"N'{schema}'")); + var args = string.Join(",", options.SchemasToExclude.Select(schema => $"N'{schema}'")); commandText += " AND s.name NOT IN (" + args + ")"; } - else if (checkpoint.SchemasToInclude.Any()) + else if (options.SchemasToInclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToInclude.Select(schema => $"N'{schema}'")); + var args = string.Join(",", options.SchemasToInclude.Select(schema => $"N'{schema}'")); commandText += " AND s.name IN (" + args + ")"; } @@ -94,7 +94,7 @@ from sys.tables t return commandText; } - public string BuildRelationshipCommandText(Checkpoint checkpoint) + public string BuildRelationshipCommandText(RespawnerOptions options) { string commandText = @" select @@ -109,9 +109,9 @@ sys.foreign_keys sfk inner join sys.schemas fk_schema on so_fk.schema_id = fk_schema.schema_id where 1=1"; - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, @@ -137,9 +137,9 @@ sys.foreign_keys sfk } } } - if (checkpoint.TablesToInclude.Any()) + if (options.TablesToInclude.Any()) { - var tablesToIncludeGroups = checkpoint.TablesToInclude + var tablesToIncludeGroups = options.TablesToInclude .GroupBy( t => t.Schema != null, t => t, @@ -165,15 +165,15 @@ sys.foreign_keys sfk } } } - if (checkpoint.SchemasToExclude.Any()) + if (options.SchemasToExclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToExclude.Select(schema => $"N'{schema}'")); + var args = string.Join(",", options.SchemasToExclude.Select(schema => $"N'{schema}'")); commandText += " AND pk_schema.name NOT IN (" + args + ")"; } - else if (checkpoint.SchemasToInclude.Any()) + else if (options.SchemasToInclude.Any()) { - var args = string.Join(",", checkpoint.SchemasToInclude.Select(schema => $"N'{schema}'")); + var args = string.Join(",", options.SchemasToInclude.Select(schema => $"N'{schema}'")); commandText += " AND pk_schema.name IN (" + args + ")"; } @@ -244,7 +244,7 @@ public string BuildReseedSql(IEnumerable
tablesToDelete) return sql; } - public string BuildTemporalTableCommandText(Checkpoint checkpoint) + public string BuildTemporalTableCommandText(RespawnerOptions options) { string commandText = @" select s.name, t.name, temp_s.name, temp_t.name @@ -254,9 +254,9 @@ from sys.tables t INNER JOIN sys.schemas temp_s on temp_t.schema_id = temp_s.schema_id WHERE t.temporal_type = 2"; - if (checkpoint.TablesToIgnore.Any()) + if (options.TablesToIgnore.Any()) { - var tablesToIgnoreGroups = checkpoint.TablesToIgnore + var tablesToIgnoreGroups = options.TablesToIgnore .GroupBy( t => t.Schema != null, t => t, diff --git a/informix-server/sqlhosts b/informix-server/sqlhosts index 81f6e0e..32fe418 100644 --- a/informix-server/sqlhosts +++ b/informix-server/sqlhosts @@ -1,6 +1,6 @@ ############################################################ ### DO NOT MODIFY THIS COMMENT SECTION -### HOST NAME = be3b19cce0df +### HOST NAME = 7de528a4b167 ############################################################ -informix onsoctcp *be3b19cce0df 9088 -informix_dr drsoctcp *be3b19cce0df 9089 +informix onsoctcp *7de528a4b167 9088 +informix_dr drsoctcp *7de528a4b167 9089