diff --git a/docker-compose.yml b/docker-compose.yml index 3f1575c6..d5315fb9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,7 +26,7 @@ services: environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: main - MYSQL_USER: user + MYSQL_USER: user # redundant MYSQL_PASSWORD: password networks: - testnet @@ -34,8 +34,10 @@ services: image: postgres:11 environment: POSTGRES_PASSWORD: password - POSTGRES_USER: user + POSTGRES_USER: root # superuser name POSTGRES_DB: main + networks: + - testnet redis: image: redis:alpine networks: diff --git a/src/DatabaseManager.php b/src/DatabaseManager.php index feeeac2f..a5bae6bd 100644 --- a/src/DatabaseManager.php +++ b/src/DatabaseManager.php @@ -36,6 +36,14 @@ class DatabaseManager $this->database->setDefaultConnection($default_connection); } + /** + * Create a database. + * @todo Should this handle prefixes? + * + * @param string $name + * @param string $driver + * @return bool + */ public function create(string $name, string $driver = null) { $this->createTenantConnection($name); @@ -50,10 +58,18 @@ class DatabaseManager if (config('tenancy.queue_database_creation', false)) { QueuedTenantDatabaseCreator::dispatch(app($databaseManagers[$driver]), $name, 'create'); } else { - app($databaseManagers[$driver])->createDatabase($name); + return app($databaseManagers[$driver])->createDatabase($name); } } + /** + * Delete a database. + * @todo Should this handle prefixes? + * + * @param string $name + * @param string $driver + * @return bool + */ public function delete(string $name, string $driver = null) { $this->createTenantConnection($name); @@ -68,7 +84,7 @@ class DatabaseManager if (config('tenancy.queue_database_deletion', false)) { QueuedTenantDatabaseDeleter::dispatch(app($databaseManagers[$driver]), $name, 'delete'); } else { - app($databaseManagers[$driver])->deleteDatabase($name); + return app($databaseManagers[$driver])->deleteDatabase($name); } } diff --git a/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php b/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php new file mode 100644 index 00000000..2f56ff38 --- /dev/null +++ b/src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php @@ -0,0 +1,19 @@ + [ 'sqlite' => 'Stancl\Tenancy\TenantDatabaseManagers\SQLiteDatabaseManager', 'mysql' => 'Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager', + 'pgsql' => 'Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLDatabaseManager', ], 'queue_database_creation' => false, 'queue_database_deletion' => false, diff --git a/tests/TenantDatabaseManagerTest.php b/tests/TenantDatabaseManagerTest.php index 150db99c..dc68ac03 100644 --- a/tests/TenantDatabaseManagerTest.php +++ b/tests/TenantDatabaseManagerTest.php @@ -14,10 +14,10 @@ class TenantDatabaseManagerTest extends TestCase public function sqlite_database_can_be_created_and_deleted() { $db_name = 'testdatabase' . $this->randomString(10) . '.sqlite'; - app(DatabaseManager::class)->create($db_name, 'sqlite'); + $this->assertTrue(app(DatabaseManager::class)->create($db_name, 'sqlite')); $this->assertFileExists(database_path($db_name)); - app(DatabaseManager::class)->delete($db_name, 'sqlite'); + $this->assertTrue(app(DatabaseManager::class)->delete($db_name, 'sqlite')); $this->assertFileNotExists(database_path($db_name)); } @@ -47,10 +47,10 @@ class TenantDatabaseManagerTest extends TestCase config()->set('database.default', 'mysql'); $db_name = 'testdatabase' . $this->randomString(10); - app(DatabaseManager::class)->create($db_name, 'mysql'); + $this->assertTrue(app(DatabaseManager::class)->create($db_name, 'mysql')); $this->assertNotEmpty(DB::select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$db_name'")); - app(DatabaseManager::class)->delete($db_name, 'mysql'); + $this->assertTrue(app(DatabaseManager::class)->delete($db_name, 'mysql')); $this->assertEmpty(DB::select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$db_name'")); } @@ -78,6 +78,47 @@ class TenantDatabaseManagerTest extends TestCase $this->assertEmpty(DB::select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$db_name'")); } + /** @test */ + public function pgsql_database_can_be_created_and_deleted() + { + if (! $this->isContainerized()) { + $this->markTestSkipped('As to not bloat your PostgreSQL instance with test databases, this test is not run by default.'); + } + + config()->set('database.default', 'pgsql'); + + $db_name = strtolower('testdatabase' . $this->randomString(10)); + $this->assertTrue(app(DatabaseManager::class)->create($db_name, 'pgsql')); + $this->assertNotEmpty(DB::select("SELECT datname FROM pg_database WHERE datname = '$db_name'")); + + $this->assertTrue(app(DatabaseManager::class)->delete($db_name, 'pgsql')); + $this->assertEmpty(DB::select("SELECT datname FROM pg_database WHERE datname = '$db_name'")); + } + + /** @test */ + public function pgsql_database_can_be_created_and_deleted_using_queued_commands() + { + if (! $this->isContainerized()) { + $this->markTestSkipped('As to not bloat your PostgreSQL instance with test databases, this test is not run by default.'); + } + + config()->set('database.default', 'pgsql'); + + $db_name = strtolower('testdatabase' . $this->randomString(10)); + + $databaseManagers = config('tenancy.database_managers'); + $job = new QueuedTenantDatabaseCreator(app($databaseManagers['pgsql']), $db_name); + $job->handle(); + + $this->assertNotEmpty(DB::select("SELECT datname FROM pg_database WHERE datname = '$db_name'")); + + $databaseManagers = config('tenancy.database_managers'); + $job = new QueuedTenantDatabaseDeleter(app($databaseManagers['pgsql']), $db_name); + $job->handle(); + + $this->assertEmpty(DB::select("SELECT datname FROM pg_database WHERE datname = '$db_name'")); + } + /** @test */ public function database_creation_can_be_queued() {