From 07ad5f60cac8b698898cdadc00a07ff63735be1e Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 10 Oct 2023 09:59:31 +0200 Subject: [PATCH] Run high-deps tests with ORM 3 and DBAL 4 --- Tests/Transport/ConnectionTest.php | 48 +++++++++++++------ .../DoctrineTransportFactoryTest.php | 12 ++++- Transport/Connection.php | 7 +-- composer.json | 2 +- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/Tests/Transport/ConnectionTest.php b/Tests/Transport/ConnectionTest.php index 5af44c4..d7c9a05 100644 --- a/Tests/Transport/ConnectionTest.php +++ b/Tests/Transport/ConnectionTest.php @@ -19,8 +19,10 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\MariaDBPlatform; use Doctrine\DBAL\Platforms\MySQL57Platform; +use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\DBAL\Platforms\OraclePlatform; use Doctrine\DBAL\Platforms\SQLServer2012Platform; +use Doctrine\DBAL\Platforms\SQLServerPlatform; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Result; use Doctrine\DBAL\Schema\AbstractSchemaManager; @@ -98,7 +100,7 @@ public function testItThrowsATransportExceptionIfItCannotAcknowledgeMessage() { $this->expectException(TransportException::class); $driverConnection = $this->getDBALConnectionMock(); - $driverConnection->method('delete')->willThrowException(new DBALException()); + $driverConnection->method('delete')->willThrowException($this->createStub(DBALException::class)); $connection = new Connection([], $driverConnection); $connection->ack('dummy_id'); @@ -108,7 +110,7 @@ public function testItThrowsATransportExceptionIfItCannotRejectMessage() { $this->expectException(TransportException::class); $driverConnection = $this->getDBALConnectionMock(); - $driverConnection->method('delete')->willThrowException(new DBALException()); + $driverConnection->method('delete')->willThrowException($this->createStub(DBALException::class)); $connection = new Connection([], $driverConnection); $connection->reject('dummy_id'); @@ -391,7 +393,7 @@ public function testGeneratedSql(AbstractPlatform $platform, string $expectedSql public static function providePlatformSql(): iterable { yield 'MySQL' => [ - new MySQL57Platform(), + class_exists(MySQLPlatform::class) ? new MySQLPlatform() : new MySQL57Platform(), 'SELECT m.* FROM messenger_messages m WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?) ORDER BY available_at ASC LIMIT 1 FOR UPDATE', ]; @@ -403,14 +405,23 @@ public static function providePlatformSql(): iterable } yield 'SQL Server' => [ - new SQLServer2012Platform(), + class_exists(SQLServerPlatform::class) && !class_exists(SQLServer2012Platform::class) ? new SQLServerPlatform() : new SQLServer2012Platform(), 'SELECT m.* FROM messenger_messages m WITH (UPDLOCK, ROWLOCK) WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?) ORDER BY available_at ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY ', ]; - yield 'Oracle' => [ - new OraclePlatform(), - 'SELECT w.id AS "id", w.body AS "body", w.headers AS "headers", w.queue_name AS "queue_name", w.created_at AS "created_at", w.available_at AS "available_at", w.delivered_at AS "delivered_at" FROM messenger_messages w WHERE w.id IN (SELECT a.id FROM (SELECT m.id FROM messenger_messages m WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?) ORDER BY available_at ASC) a WHERE ROWNUM <= 1) FOR UPDATE', - ]; + if (!class_exists(MySQL57Platform::class)) { + // DBAL >= 4 + yield 'Oracle' => [ + new OraclePlatform(), + 'SELECT w.id AS "id", w.body AS "body", w.headers AS "headers", w.queue_name AS "queue_name", w.created_at AS "created_at", w.available_at AS "available_at", w.delivered_at AS "delivered_at" FROM messenger_messages w WHERE w.id IN (SELECT m.id FROM messenger_messages m WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?) ORDER BY available_at ASC FETCH NEXT 1 ROWS ONLY) FOR UPDATE', + ]; + } else { + // DBAL < 4 + yield 'Oracle' => [ + new OraclePlatform(), + 'SELECT w.id AS "id", w.body AS "body", w.headers AS "headers", w.queue_name AS "queue_name", w.created_at AS "created_at", w.available_at AS "available_at", w.delivered_at AS "delivered_at" FROM messenger_messages w WHERE w.id IN (SELECT a.id FROM (SELECT m.id FROM messenger_messages m WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?) ORDER BY available_at ASC) a WHERE ROWNUM <= 1) FOR UPDATE', + ]; + } } public function testConfigureSchema() @@ -483,7 +494,7 @@ public function testFindAllSqlGenerated(AbstractPlatform $platform, string $expe public function provideFindAllSqlGeneratedByPlatform(): iterable { yield 'MySQL' => [ - new MySQL57Platform(), + class_exists(MySQLPlatform::class) ? new MySQLPlatform() : new MySQL57Platform(), 'SELECT m.* FROM messenger_messages m WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?) LIMIT 50', ]; @@ -495,13 +506,22 @@ public function provideFindAllSqlGeneratedByPlatform(): iterable } yield 'SQL Server' => [ - new SQLServer2012Platform(), + class_exists(SQLServerPlatform::class) && !class_exists(SQLServer2012Platform::class) ? new SQLServerPlatform() : new SQLServer2012Platform(), 'SELECT m.* FROM messenger_messages m WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?) ORDER BY (SELECT 0) OFFSET 0 ROWS FETCH NEXT 50 ROWS ONLY', ]; - yield 'Oracle' => [ - new OraclePlatform(), - 'SELECT a.* FROM (SELECT m.id AS "id", m.body AS "body", m.headers AS "headers", m.queue_name AS "queue_name", m.created_at AS "created_at", m.available_at AS "available_at", m.delivered_at AS "delivered_at" FROM messenger_messages m WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?)) a WHERE ROWNUM <= 50', - ]; + if (!class_exists(MySQL57Platform::class)) { + // DBAL >= 4 + yield 'Oracle' => [ + new OraclePlatform(), + 'SELECT m.id AS "id", m.body AS "body", m.headers AS "headers", m.queue_name AS "queue_name", m.created_at AS "created_at", m.available_at AS "available_at", m.delivered_at AS "delivered_at" FROM messenger_messages m WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?) FETCH NEXT 50 ROWS ONLY', + ]; + } else { + // DBAL < 4 + yield 'Oracle' => [ + new OraclePlatform(), + 'SELECT a.* FROM (SELECT m.id AS "id", m.body AS "body", m.headers AS "headers", m.queue_name AS "queue_name", m.created_at AS "created_at", m.available_at AS "available_at", m.delivered_at AS "delivered_at" FROM messenger_messages m WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?)) a WHERE ROWNUM <= 50', + ]; + } } } diff --git a/Tests/Transport/DoctrineTransportFactoryTest.php b/Tests/Transport/DoctrineTransportFactoryTest.php index 54dd7ab..6e108ba 100644 --- a/Tests/Transport/DoctrineTransportFactoryTest.php +++ b/Tests/Transport/DoctrineTransportFactoryTest.php @@ -46,7 +46,11 @@ public function testCreateTransport() $schemaConfig = $this->createMock(SchemaConfig::class); $platform = $this->createMock(AbstractPlatform::class); $schemaManager->method('createSchemaConfig')->willReturn($schemaConfig); - $driverConnection->method('getSchemaManager')->willReturn($schemaManager); + $driverConnection->method( + method_exists(\Doctrine\DBAL\Connection::class, 'createSchemaManager') + ? 'createSchemaManager' + : 'getSchemaManager' + )->willReturn($schemaManager); $driverConnection->method('getDatabasePlatform')->willReturn($platform); $registry = $this->createMock(ConnectionRegistry::class); @@ -70,7 +74,11 @@ public function testCreateTransportNotifyWithPostgreSQLPlatform() $schemaConfig = $this->createMock(SchemaConfig::class); $platform = $this->createMock(PostgreSQLPlatform::class); $schemaManager->method('createSchemaConfig')->willReturn($schemaConfig); - $driverConnection->method('getSchemaManager')->willReturn($schemaManager); + $driverConnection->method( + method_exists(\Doctrine\DBAL\Connection::class, 'createSchemaManager') + ? 'createSchemaManager' + : 'getSchemaManager' + )->willReturn($schemaManager); $driverConnection->method('getDatabasePlatform')->willReturn($platform); $registry = $this->createMock(ConnectionRegistry::class); diff --git a/Transport/Connection.php b/Transport/Connection.php index 6bb601c..fe1b7a2 100644 --- a/Transport/Connection.php +++ b/Transport/Connection.php @@ -177,11 +177,8 @@ public function get(): ?array // Append pessimistic write lock to FROM clause if db platform supports it $sql = $query->getSQL(); - if (($fromPart = $query->getQueryPart('from')) && - ($table = $fromPart[0]['table'] ?? null) && - ($alias = $fromPart[0]['alias'] ?? null) - ) { - $fromClause = sprintf('%s %s', $table, $alias); + if (preg_match('/FROM (.+) WHERE/', (string) $sql, $matches)) { + $fromClause = $matches[1]; $sql = str_replace( sprintf('FROM %s WHERE', $fromClause), sprintf('FROM %s WHERE', $this->driverConnection->getDatabasePlatform()->appendLockHint($fromClause, LockMode::PESSIMISTIC_WRITE)), diff --git a/composer.json b/composer.json index 3a9494a..e1490a7 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "symfony/service-contracts": "^1.1|^2|^3" }, "require-dev": { - "doctrine/dbal": "^2.13|^3.0", + "doctrine/dbal": "^2.13|^3|^4", "doctrine/persistence": "^1.3|^2|^3", "symfony/property-access": "^4.4|^5.0|^6.0", "symfony/serializer": "^4.4|^5.0|^6.0"