Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PostgreSQL DB driver #52

Merged
merged 17 commits into from Jul 12, 2019
6 changes: 4 additions & 2 deletions docker-compose.yml
Expand Up @@ -26,16 +26,18 @@ services:
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: main
MYSQL_USER: user
MYSQL_USER: user # redundant
MYSQL_PASSWORD: password
networks:
- testnet
postgres:
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:
Expand Down
20 changes: 18 additions & 2 deletions src/DatabaseManager.php
Expand Up @@ -36,6 +36,14 @@ public function disconnect()
$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);
Expand All @@ -50,10 +58,18 @@ public function create(string $name, string $driver = null)
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);
Expand All @@ -68,7 +84,7 @@ public function delete(string $name, string $driver = null)
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);
}
}

Expand Down
19 changes: 19 additions & 0 deletions src/TenantDatabaseManagers/PostgreSQLDatabaseManager.php
@@ -0,0 +1,19 @@
<?php

namespace Stancl\Tenancy\TenantDatabaseManagers;

use Illuminate\Support\Facades\DB;
use Stancl\Tenancy\Interfaces\TenantDatabaseManager;

class PostgreSQLDatabaseManager implements TenantDatabaseManager
{
public function createDatabase(string $name): bool
{
return DB::statement("CREATE DATABASE $name WITH TEMPLATE=template0");
}

public function deleteDatabase(string $name): bool
{
return DB::statement("DROP DATABASE $name");
}
}
1 change: 1 addition & 0 deletions src/config/tenancy.php
Expand Up @@ -39,6 +39,7 @@
'database_managers' => [
'sqlite' => 'Stancl\Tenancy\TenantDatabaseManagers\SQLiteDatabaseManager',
'mysql' => 'Stancl\Tenancy\TenantDatabaseManagers\MySQLDatabaseManager',
'pgsql' => 'Stancl\Tenancy\TenantDatabaseManagers\PostgreSQLDatabaseManager',
],
'queue_database_creation' => false,
'queue_database_deletion' => false,
Expand Down
49 changes: 45 additions & 4 deletions tests/TenantDatabaseManagerTest.php
Expand Up @@ -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));
}

Expand Down Expand Up @@ -47,10 +47,10 @@ public function mysql_database_can_be_created_and_deleted()
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'"));
}

Expand Down Expand Up @@ -78,6 +78,47 @@ public function mysql_database_can_be_created_and_deleted_using_queued_commands(
$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'"));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a correct way of checking that a database exists?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, but Postgres converts all DB names to lowercase while the WHERE clause does not.


$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()
{
Expand Down