|
| 1 | +using Microsoft.EntityFrameworkCore; |
| 2 | +using Microsoft.EntityFrameworkCore.Infrastructure; |
| 3 | +using Npgsql; |
| 4 | + |
| 5 | +namespace TestSupport.EfHelpers.Internal |
| 6 | +{ |
| 7 | + internal static class PostgreSqlDropSchemaEnsureClean |
| 8 | + { |
| 9 | + /// <summary> |
| 10 | + /// This uses the "DROP SCHEMA" approach (see https://stackoverflow.com/a/13823560/1434764) |
| 11 | + /// to remove all the tables, extensions, functions, collations. |
| 12 | + /// The SQL in this method was provided by Shay Rojansky, github @roji |
| 13 | + /// </summary> |
| 14 | + /// <param name="databaseFacade"></param> |
| 15 | + /// <param name="setUpSchema"></param> |
| 16 | + public static void FasterPostgreSqlEnsureClean(this DatabaseFacade databaseFacade, bool setUpSchema = true) |
| 17 | + { |
| 18 | + var connectionString = databaseFacade.GetDbConnection().ConnectionString; |
| 19 | + if (connectionString.DatabaseExists()) |
| 20 | + { |
| 21 | + var conn = new NpgsqlConnection(connectionString); |
| 22 | + conn.Open(); |
| 23 | + |
| 24 | + var dropPublicSchemaCommand = new NpgsqlCommand |
| 25 | + { |
| 26 | + Connection = conn, |
| 27 | + CommandText = @" |
| 28 | +DO $$ |
| 29 | +DECLARE |
| 30 | + r RECORD; |
| 31 | +BEGIN |
| 32 | + FOR r IN (SELECT nspname FROM pg_namespace WHERE nspname NOT IN ('pg_toast', 'pg_catalog', 'information_schema')) |
| 33 | + LOOP |
| 34 | + EXECUTE 'DROP SCHEMA ' || quote_ident(r.nspname) || ' CASCADE'; |
| 35 | + END LOOP; |
| 36 | + EXECUTE 'CREATE SCHEMA public; GRANT ALL ON SCHEMA public TO postgres; GRANT ALL ON SCHEMA public TO public'; |
| 37 | +END $$" |
| 38 | + }; |
| 39 | + dropPublicSchemaCommand.ExecuteNonQuery(); |
| 40 | + } |
| 41 | + |
| 42 | + if (setUpSchema) |
| 43 | + databaseFacade.EnsureCreated(); |
| 44 | + } |
| 45 | + |
| 46 | + private static bool DatabaseExists(this string connectionString) |
| 47 | + { |
| 48 | + var builder = new NpgsqlConnectionStringBuilder(connectionString); |
| 49 | + var orgDbStartsWith = builder.Database; |
| 50 | + builder.Database = "postgres"; |
| 51 | + var newConnectionString = builder.ToString(); |
| 52 | + using var conn = new NpgsqlConnection(newConnectionString); |
| 53 | + conn.Open(); |
| 54 | + |
| 55 | + using var cmd = new NpgsqlCommand($"SELECT COUNT(*) FROM pg_catalog.pg_database WHERE datname='{orgDbStartsWith}'", conn); |
| 56 | + return (long)cmd.ExecuteScalar() == 1; |
| 57 | + } |
| 58 | + } |
| 59 | +} |
0 commit comments