diff --git a/Makefile b/Makefile
index 01f437b8..4f9b56d6 100644
--- a/Makefile
+++ b/Makefile
@@ -41,11 +41,11 @@ phpunit-integration: vendor
.PHONY: phpunit-integration-postgres
phpunit-integration-postgres: vendor ## run phpunit integration tests on postgres
- DB_URL="pdo-pgsql://postgres:postgres@localhost:5432/eventstore?charset=utf8" vendor/bin/phpunit --testsuite=integration
+ DB_URL="pdo-pgsql://postgres:postgres@127.0.0.1:5432/eventstore?charset=utf8" vendor/bin/phpunit --testsuite=integration
.PHONY: phpunit-integration-mysql
phpunit-integration-mysql: vendor ## run phpunit integration tests on mysql
- DB_URL="pdo-mysql://root@localhost:3306/eventstore?charset=utf8" vendor/bin/phpunit --testsuite=integration
+ DB_URL="pdo-mysql://root@127.0.0.1:3306/eventstore?charset=utf8" vendor/bin/phpunit --testsuite=integration
.PHONY: phpunit-unit
phpunit-unit: vendor ## run phpunit unit tests
diff --git a/baseline.xml b/baseline.xml
index 7504e13d..2e51abc6 100644
--- a/baseline.xml
+++ b/baseline.xml
@@ -95,6 +95,12 @@
+
+
+
+
+
+
diff --git a/src/Cryptography/DoctrineCipherKeyStore.php b/src/Cryptography/DoctrineCipherKeyStore.php
index 2bfb00da..fdd4c850 100644
--- a/src/Cryptography/DoctrineCipherKeyStore.php
+++ b/src/Cryptography/DoctrineCipherKeyStore.php
@@ -6,6 +6,7 @@
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Schema\Schema;
+use Patchlevel\EventSourcing\Schema\DoctrineHelper;
use Patchlevel\EventSourcing\Schema\DoctrineSchemaConfigurator;
use Patchlevel\Hydrator\Cryptography\Cipher\CipherKey;
use Patchlevel\Hydrator\Cryptography\Store\CipherKeyNotExists;
@@ -80,7 +81,7 @@ public function remove(string $id): void
public function configureSchema(Schema $schema, Connection $connection): void
{
- if ($connection !== $this->connection) {
+ if (!DoctrineHelper::sameDatabase($this->connection, $connection)) {
return;
}
diff --git a/src/Schema/DoctrineHelper.php b/src/Schema/DoctrineHelper.php
new file mode 100644
index 00000000..889c9cf6
--- /dev/null
+++ b/src/Schema/DoctrineHelper.php
@@ -0,0 +1,44 @@
+getParams() === $connectionB->getParams()) {
+ return true;
+ }
+
+ $checkTable = 'same_db_check_' . bin2hex(random_bytes(7));
+ $connectionA->executeStatement(sprintf('CREATE TABLE %s (id INTEGER NOT NULL)', $checkTable));
+
+ try {
+ $connectionB->executeStatement(sprintf('DROP TABLE %s', $checkTable));
+ } catch (Throwable) {
+ // ignore
+ }
+
+ try {
+ $connectionA->executeStatement(sprintf('DROP TABLE %s', $checkTable));
+
+ return false;
+ } catch (TableNotFoundException) {
+ return true;
+ }
+ }
+}
diff --git a/src/Store/DoctrineDbalStore.php b/src/Store/DoctrineDbalStore.php
index 76c775bd..902d6c41 100644
--- a/src/Store/DoctrineDbalStore.php
+++ b/src/Store/DoctrineDbalStore.php
@@ -21,6 +21,7 @@
use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer;
use Patchlevel\EventSourcing\Message\Serializer\HeadersSerializer;
+use Patchlevel\EventSourcing\Schema\DoctrineHelper;
use Patchlevel\EventSourcing\Schema\DoctrineSchemaConfigurator;
use Patchlevel\EventSourcing\Serializer\EventSerializer;
use Patchlevel\EventSourcing\Store\Criteria\AggregateIdCriterion;
@@ -314,7 +315,7 @@ public function transactional(Closure $function): void
public function configureSchema(Schema $schema, Connection $connection): void
{
- if ($this->connection !== $connection) {
+ if (!DoctrineHelper::sameDatabase($this->connection, $connection)) {
return;
}
diff --git a/src/Store/StreamDoctrineDbalStore.php b/src/Store/StreamDoctrineDbalStore.php
index 69ef4b9e..83a24a24 100644
--- a/src/Store/StreamDoctrineDbalStore.php
+++ b/src/Store/StreamDoctrineDbalStore.php
@@ -21,6 +21,7 @@
use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Message\Serializer\DefaultHeadersSerializer;
use Patchlevel\EventSourcing\Message\Serializer\HeadersSerializer;
+use Patchlevel\EventSourcing\Schema\DoctrineHelper;
use Patchlevel\EventSourcing\Schema\DoctrineSchemaConfigurator;
use Patchlevel\EventSourcing\Serializer\EventSerializer;
use Patchlevel\EventSourcing\Store\Criteria\ArchivedCriterion;
@@ -396,7 +397,7 @@ public function archive(Criteria|null $criteria = null): void
public function configureSchema(Schema $schema, Connection $connection): void
{
- if ($this->connection !== $connection) {
+ if (!DoctrineHelper::sameDatabase($this->connection, $connection)) {
return;
}
diff --git a/src/Subscription/Store/DoctrineSubscriptionStore.php b/src/Subscription/Store/DoctrineSubscriptionStore.php
index 08cde34d..424f1cce 100644
--- a/src/Subscription/Store/DoctrineSubscriptionStore.php
+++ b/src/Subscription/Store/DoctrineSubscriptionStore.php
@@ -15,6 +15,7 @@
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
use Patchlevel\EventSourcing\Clock\SystemClock;
+use Patchlevel\EventSourcing\Schema\DoctrineHelper;
use Patchlevel\EventSourcing\Schema\DoctrineSchemaConfigurator;
use Patchlevel\EventSourcing\Subscription\RunMode;
use Patchlevel\EventSourcing\Subscription\Status;
@@ -208,6 +209,10 @@ public function inLock(Closure $closure): mixed
public function configureSchema(Schema $schema, Connection $connection): void
{
+ if (!DoctrineHelper::sameDatabase($this->connection, $connection)) {
+ return;
+ }
+
$table = $schema->createTable($this->tableName);
$table->addColumn('id', Types::STRING)
diff --git a/tests/DbalManager.php b/tests/DbalManager.php
index c4a39af7..240e5c21 100644
--- a/tests/DbalManager.php
+++ b/tests/DbalManager.php
@@ -7,6 +7,7 @@
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\AbstractSQLiteDriver;
use Doctrine\DBAL\DriverManager;
+use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Tools\DsnParser;
use Patchlevel\EventSourcing\Console\DoctrineHelper;
use RuntimeException;
@@ -45,6 +46,14 @@ public static function createConnection(string $dbName = self::DEFAULT_DB_NAME):
$databases = $schemaManager->listDatabases();
if (in_array($dbName, $databases, true)) {
+ if ($tempConnection->getDatabasePlatform() instanceof PostgreSQLPlatform) {
+ $tempConnection->executeStatement("
+ SELECT pg_terminate_backend(pid)
+ FROM pg_stat_activity
+ WHERE datname = '{$dbName}';
+ ");
+ }
+
$schemaManager->dropDatabase($dbName);
}
diff --git a/tests/Integration/Store/DoctrineDbalStoreTest.php b/tests/Integration/Store/DoctrineDbalStoreTest.php
index 3eee96ad..04511fc7 100644
--- a/tests/Integration/Store/DoctrineDbalStoreTest.php
+++ b/tests/Integration/Store/DoctrineDbalStoreTest.php
@@ -6,6 +6,7 @@
use DateTimeImmutable;
use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\Schema\Schema;
use Patchlevel\EventSourcing\Aggregate\AggregateHeader;
use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;
@@ -224,4 +225,38 @@ public function testLoad(): void
$stream?->close();
}
}
+
+ public function testConfigureSchemaSameDatabase(): void
+ {
+ $connection = DbalManager::createConnection();
+ $otherConnection = DbalManager::createConnection();
+
+ $store = new DoctrineDbalStore(
+ $connection,
+ DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']),
+ );
+
+ $schema = new Schema();
+
+ $store->configureSchema($schema, $otherConnection);
+
+ self::assertTrue($schema->hasTable('eventstore'));
+ }
+
+ public function testConfigureSchemaNotSameDatabase(): void
+ {
+ $connection = DbalManager::createConnection();
+ $otherConnection = DbalManager::createConnection('other');
+
+ $store = new DoctrineDbalStore(
+ $connection,
+ DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']),
+ );
+
+ $schema = new Schema();
+
+ $store->configureSchema($schema, $otherConnection);
+
+ self::assertFalse($schema->hasTable('eventstore'));
+ }
}
diff --git a/tests/Integration/Store/StreamDoctrineDbalStoreTest.php b/tests/Integration/Store/StreamDoctrineDbalStoreTest.php
index 9d22d7b5..9b83b285 100644
--- a/tests/Integration/Store/StreamDoctrineDbalStoreTest.php
+++ b/tests/Integration/Store/StreamDoctrineDbalStoreTest.php
@@ -6,6 +6,7 @@
use DateTimeImmutable;
use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\Schema\Schema;
use Patchlevel\EventSourcing\Clock\FrozenClock;
use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;
@@ -538,4 +539,40 @@ public function testRemove(): void
self::assertEquals(['foo'], $streams);
}
+
+ public function testConfigureSchemaSameDatabase(): void
+ {
+ $connection = DbalManager::createConnection();
+ $otherConnection = DbalManager::createConnection();
+
+ $store = new StreamDoctrineDbalStore(
+ $connection,
+ DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']),
+ clock: $this->clock,
+ );
+
+ $schema = new Schema();
+
+ $store->configureSchema($schema, $otherConnection);
+
+ self::assertTrue($schema->hasTable('event_store'));
+ }
+
+ public function testConfigureSchemaNotSameDatabase(): void
+ {
+ $connection = DbalManager::createConnection();
+ $otherConnection = DbalManager::createConnection('other');
+
+ $store = new StreamDoctrineDbalStore(
+ $connection,
+ DefaultEventSerializer::createFromPaths([__DIR__ . '/Events']),
+ clock: $this->clock,
+ );
+
+ $schema = new Schema();
+
+ $store->configureSchema($schema, $otherConnection);
+
+ self::assertFalse($schema->hasTable('event_store'));
+ }
}
diff --git a/tests/Unit/Store/DoctrineDbalStoreTest.php b/tests/Unit/Store/DoctrineDbalStoreTest.php
index b6807935..0d968ff5 100644
--- a/tests/Unit/Store/DoctrineDbalStoreTest.php
+++ b/tests/Unit/Store/DoctrineDbalStoreTest.php
@@ -1375,9 +1375,11 @@ public function testWait(): void
$doctrineDbalStore->wait(100);
}
- public function testConfigureSchemaWithDifferentConnections(): void
+ public function testConfigureSchemaWithDifferentDatabase(): void
{
$connection = $this->createMock(Connection::class);
+ $connection->expects($this->once())->method('getParams')->willReturn(['dbname' => 'db']);
+
$eventSerializer = $this->createMock(EventSerializer::class);
$headersSerializer = $this->createMock(HeadersSerializer::class);
@@ -1386,8 +1388,12 @@ public function testConfigureSchemaWithDifferentConnections(): void
$eventSerializer,
$headersSerializer,
);
+
+ $differentConnection = $this->createMock(Connection::class);
+ $differentConnection->expects($this->once())->method('getParams')->willReturn(['dbname' => 'db2']);
+
$schema = new Schema();
- $doctrineDbalStore->configureSchema($schema, $this->createMock(Connection::class));
+ $doctrineDbalStore->configureSchema($schema, $differentConnection);
self::assertEquals(new Schema(), $schema);
}
diff --git a/tests/Unit/Store/StreamDoctrineDbalStoreTest.php b/tests/Unit/Store/StreamDoctrineDbalStoreTest.php
index 1e9d472a..c78414c2 100644
--- a/tests/Unit/Store/StreamDoctrineDbalStoreTest.php
+++ b/tests/Unit/Store/StreamDoctrineDbalStoreTest.php
@@ -1404,9 +1404,11 @@ public function testWait(): void
$doctrineDbalStore->wait(100);
}
- public function testConfigureSchemaWithDifferentConnections(): void
+ public function testConfigureSchemaWithDifferentDatabase(): void
{
$connection = $this->createMock(Connection::class);
+ $connection->expects($this->once())->method('getParams')->willReturn(['dbname' => 'db']);
+
$eventSerializer = $this->createMock(EventSerializer::class);
$headersSerializer = $this->createMock(HeadersSerializer::class);
@@ -1415,8 +1417,12 @@ public function testConfigureSchemaWithDifferentConnections(): void
$eventSerializer,
$headersSerializer,
);
+
+ $differentConnection = $this->createMock(Connection::class);
+ $connection->expects($this->once())->method('getParams')->willReturn(['dbname' => 'db2']);
+
$schema = new Schema();
- $doctrineDbalStore->configureSchema($schema, $this->createMock(Connection::class));
+ $doctrineDbalStore->configureSchema($schema, $differentConnection);
self::assertEquals(new Schema(), $schema);
}