From 01a1caa90f14bca1fd06f23b6b9c4bca3b704641 Mon Sep 17 00:00:00 2001 From: Stefano Kowalke Date: Mon, 30 Apr 2018 12:28:38 +0200 Subject: [PATCH] Support PostgreSQL DB The current implementation does not support PostgreSQL because it creates the tables for the read models manually instead using the DBAL SchemaBuilder. Additionally it uses a wrong key for the database configuration. --- .../Projection/Todo/TodoReadModel.php | 74 ++++++++----------- .../Projection/Todo/TodoReminderReadModel.php | 68 ++++++++--------- .../Projection/User/UserFinder.php | 15 ++++ .../Projection/User/UserReadModel.php | 69 ++++++++--------- .../ProophessorDoServiceProvider.php | 2 +- 5 files changed, 106 insertions(+), 122 deletions(-) diff --git a/app/ProophessorDo/Projection/Todo/TodoReadModel.php b/app/ProophessorDo/Projection/Todo/TodoReadModel.php index bab92a4..e08ab94 100644 --- a/app/ProophessorDo/Projection/Todo/TodoReadModel.php +++ b/app/ProophessorDo/Projection/Todo/TodoReadModel.php @@ -23,70 +23,58 @@ final class TodoReadModel extends AbstractReadModel */ private $connection; + /** @var \Doctrine\DBAL\Platforms\AbstractPlatform */ + private $platform; + + public function __construct(Connection $connection) { $this->connection = $connection; + $this->platform = $this->connection->getDatabasePlatform(); } + /** + * @throws \Doctrine\DBAL\DBALException + */ public function init(): void { $tableName = Table::TODO; - $sql = <<connection->prepare($sql); - $statement->execute(); + $schema = new \Doctrine\DBAL\Schema\Schema(); + + $table = $schema->createTable($tableName); + $table->addColumn('id', 'string', ['unsigned' => true, 'length' => 36, 'notnull' => true]); + $table->addColumn('assignee_id', 'string', ['unsigned' => true, 'length' => 36, 'notnull' => true]); + $table->addColumn('text', 'text', ['notnull' => true]); + $table->addColumn('status', 'string', ['length' => 7, 'notnull' => true]); + $table->addColumn('deadline', 'string', ['length' => 30, 'default' => null]); + $table->addColumn('reminder', 'string', ['length' => 30, 'default' => null]); + $table->setPrimaryKey(['id']); + $table->addIndex(['assignee_id', 'status'], 'idx_a_status'); + $table->addIndex(['status'], 'idx_status'); + + foreach ($schema->toSql($this->platform) as $query) { + $statement = $this->connection->prepare($query); + $statement->execute(); + } } public function isInitialized(): bool { - $tableName = Table::TODO; - - $sql = "SHOW TABLES LIKE '$tableName';"; - - $statement = $this->connection->prepare($sql); - $statement->execute(); - - $result = $statement->fetch(); - - if (false === $result) { - return false; - } - - return true; + return $this->connection->getSchemaManager()->tablesExist([Table::TODO]); } + /** + * @throws \Doctrine\DBAL\DBALException + */ public function reset(): void { - $tableName = Table::TODO; - - $sql = "TRUNCATE TABLE '$tableName';"; - EOT; - - $statement = $this->connection->prepare($sql); - $statement->execute(); + $this->connection->executeUpdate($this->platform->getTruncateTableSQL(Table::TODO, true)); } public function delete(): void { - $tableName = Table::TODO; - - $sql = "DROP TABLE $tableName;"; - - $statement = $this->connection->prepare($sql); - $statement->execute(); + $this->connection->getSchemaManager()->dropTable(Table::TODO); } protected function insert(array $data): void diff --git a/app/ProophessorDo/Projection/Todo/TodoReminderReadModel.php b/app/ProophessorDo/Projection/Todo/TodoReminderReadModel.php index 8b9d9ed..fabf7a1 100644 --- a/app/ProophessorDo/Projection/Todo/TodoReminderReadModel.php +++ b/app/ProophessorDo/Projection/Todo/TodoReminderReadModel.php @@ -23,65 +23,53 @@ final class TodoReminderReadModel extends AbstractReadModel */ private $connection; + /** @var \Doctrine\DBAL\Platforms\AbstractPlatform */ + private $platform; + + public function __construct(Connection $connection) { $this->connection = $connection; + $this->platform = $this->connection->getDatabasePlatform(); } + /** + * @throws \Doctrine\DBAL\DBALException + */ public function init(): void { $tableName = Table::TODO_REMINDER; - $sql = <<connection->prepare($sql); - $statement->execute(); - } - - public function isInitialized(): bool - { - $tableName = Table::TODO_REMINDER; - - $sql = "SHOW TABLES LIKE '$tableName';"; - - $statement = $this->connection->prepare($sql); - $statement->execute(); + $schema = new \Doctrine\DBAL\Schema\Schema(); - $result = $statement->fetch(); + $table = $schema->createTable($tableName); + $table->addColumn('todo_id', 'string', ['unsigned' => true, 'length' => 36, 'notnull' => true]); + $table->addColumn('reminder', 'string', ['length' => 30, 'notnull' => true]); + $table->addColumn('status', 'string', ['length' => 10, 'notnull' => true]); + $table->setPrimaryKey(['todo_id']); - if (false === $result) { - return false; + foreach ($schema->toSql($this->platform) as $query) { + $statement = $this->connection->prepare($query); + $statement->execute(); } + } - return true; + public function isInitialized(): bool + { + return $this->connection->getSchemaManager()->tablesExist([Table::TODO_REMINDER]); } + /** + * @throws \Doctrine\DBAL\DBALException + */ public function reset(): void { - $tableName = Table::TODO_REMINDER; - - $sql = "TRUNCATE TABLE '$tableName';"; - EOT; - - $statement = $this->connection->prepare($sql); - $statement->execute(); + $this->connection->executeUpdate($this->platform->getTruncateTableSQL(Table::TODO_REMINDER, true)); } public function delete(): void { - $tableName = Table::TODO_REMINDER; - - $sql = "DROP TABLE $tableName;"; - - $statement = $this->connection->prepare($sql); - $statement->execute(); + $this->connection->getSchemaManager()->dropTable(Table::TODO_REMINDER); } protected function insert(array $data): void @@ -98,6 +86,10 @@ protected function update(array $data, array $identifier): void ); } + /** + * @param array $query + * @throws \Doctrine\DBAL\Exception\InvalidArgumentException + */ protected function remove(array $query): void { $this->connection->delete( diff --git a/app/ProophessorDo/Projection/User/UserFinder.php b/app/ProophessorDo/Projection/User/UserFinder.php index ebf1d69..09079fa 100644 --- a/app/ProophessorDo/Projection/User/UserFinder.php +++ b/app/ProophessorDo/Projection/User/UserFinder.php @@ -33,6 +33,11 @@ public function findAll(): array return $this->connection->fetchAll(sprintf('SELECT * FROM %s', Table::USER)); } + /** + * @param string $userId + * @return null|\stdClass + * @throws \Doctrine\DBAL\DBALException + */ public function findById(string $userId): ?\stdClass { $stmt = $this->connection->prepare(sprintf('SELECT * FROM %s WHERE id = :user_id', Table::USER)); @@ -48,6 +53,11 @@ public function findById(string $userId): ?\stdClass return $result; } + /** + * @param string $emailAddress + * @return null|\stdClass + * @throws \Doctrine\DBAL\DBALException + */ public function findOneByEmailAddress(string $emailAddress): ?\stdClass { $stmt = $this->connection->prepare(sprintf('SELECT * FROM %s WHERE email = :email LIMIT 1', Table::USER)); @@ -63,6 +73,11 @@ public function findOneByEmailAddress(string $emailAddress): ?\stdClass return $result; } + /** + * @param string $todoId + * @return null|\stdClass + * @throws \Doctrine\DBAL\DBALException + */ public function findUserOfTodo(string $todoId): ?\stdClass { $stmt = $this->connection->prepare(sprintf( diff --git a/app/ProophessorDo/Projection/User/UserReadModel.php b/app/ProophessorDo/Projection/User/UserReadModel.php index b7732fb..ea819df 100644 --- a/app/ProophessorDo/Projection/User/UserReadModel.php +++ b/app/ProophessorDo/Projection/User/UserReadModel.php @@ -13,6 +13,7 @@ namespace Prooph\ProophessorDo\Projection\User; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Platforms\PostgreSqlPlatform; use Prooph\EventStore\Projection\AbstractReadModel; use Prooph\ProophessorDo\Projection\Table; @@ -23,67 +24,55 @@ final class UserReadModel extends AbstractReadModel */ private $connection; + /** @var \Doctrine\DBAL\Platforms\AbstractPlatform */ + private $platform; + public function __construct(Connection $connection) { $this->connection = $connection; + $this->platform = $this->connection->getDatabasePlatform(); } + /** + * @throws \Doctrine\DBAL\DBALException + */ public function init(): void { $tableName = Table::USER; - $sql = <<connection->prepare($sql); - $statement->execute(); - } + $schema = new \Doctrine\DBAL\Schema\Schema(); - public function isInitialized(): bool - { - $tableName = Table::USER; - - $sql = "SHOW TABLES LIKE '$tableName';"; - - $statement = $this->connection->prepare($sql); - $statement->execute(); + $table = $schema->createTable($tableName); + $table->addColumn('id', 'string', ['unsigned' => true, 'length' => 36, 'notnull' => true]); + $table->addColumn('name', 'string', ['length' => 50, 'notnull' => true]); + $table->addColumn('email', 'string', ['length' => 100, 'notnull' => true]); + $table->addColumn('open_todos', 'integer', ['length' => 11, 'notnull' => true, 'default' => 0]); + $table->addColumn('done_todos', 'integer', ['length' => 11, 'notnull' => true, 'default' => 0]); + $table->addColumn('expired_todos', 'integer', ['length' => 32, 'notnull' => true, 'default' => 0]); + $table->setPrimaryKey(['id']); - $result = $statement->fetch(); - - if (false === $result) { - return false; + foreach ($schema->toSql($this->platform) as $query) { + $statement = $this->connection->prepare($query); + $statement->execute(); } + } - return true; + public function isInitialized(): bool + { + return $this->connection->getSchemaManager()->tablesExist([Table::USER]); } + /** + * @throws \Doctrine\DBAL\DBALException + */ public function reset(): void { - $tableName = Table::USER; - - $sql = "TRUNCATE TABLE $tableName;"; - - $statement = $this->connection->prepare($sql); - $statement->execute(); + $this->connection->executeUpdate($this->platform->getTruncateTableSQL(Table::USER, true)); } public function delete(): void { - $tableName = Table::USER; - - $sql = "DROP TABLE $tableName;"; - - $statement = $this->connection->prepare($sql); - $statement->execute(); + $this->connection->getSchemaManager()->dropTable(Table::USER); } protected function insert(array $data): void diff --git a/app/Providers/ProophessorDoServiceProvider.php b/app/Providers/ProophessorDoServiceProvider.php index 3df40d7..2879595 100644 --- a/app/Providers/ProophessorDoServiceProvider.php +++ b/app/Providers/ProophessorDoServiceProvider.php @@ -23,7 +23,7 @@ public function register(): void case 'mysql': $driver = 'pdo_mysql'; break; - case 'postgres': + case 'pgsql': $driver = 'pdo_pgsql'; }