8000 bug #49317 [Messenger] Fix warning message on failed messenger show c… · symfony/symfony@0c5246f · GitHub
[go: up one dir, main page]

Skip to content

Commit 0c5246f

Browse files
bug #49317 [Messenger] Fix warning message on failed messenger show command (gstapinato)
This PR was merged into the 5.4 branch. Discussion ---------- [Messenger] Fix warning message on failed messenger show command Can only be reproduced on Oracle Databases. | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #49262 | License | MIT Fix warning message on failed messenger show command Commits ------- 4ad8101 [Messenger] Fix warning message on failed messenger show command
2 parents 8b65de5 + 4ad8101 commit 0c5246f

File tree

2 files changed

+80
-18
lines changed

2 files changed

+80
-18
lines changed

src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/ConnectionTest.php

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ public static function providePlatformSql(): iterable
401401

402402
yield 'Oracle' => [
403403
new OraclePlatform(),
404-
'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.* 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',
404+
'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',
405405
];
406406
}
407407

@@ -437,4 +437,56 @@ public function testConfigureSchemaTableExists()
437437
$table = $schema->getTable('messenger_messages');
438438
$this->assertEmpty($table->getColumns(), 'The table was not overwritten');
439439
}
440+
441+
/**
442+
* @dataProvider provideFindAllSqlGeneratedByPlatform
443+
*/
444+
public function testFindAllSqlGenerated(AbstractPlatform $platform, string $expectedSql)
445+
{
446+
$driverConnection = $this->createMock(DBALConnection::class);
447+
$driverConnection->method('getDatabasePlatform')->willReturn($platform);
448+
$driverConnection->method('createQueryBuilder')->willReturnCallback(function () use ($driverConnection) {
449+
return new QueryBuilder($driverConnection);
450+
});
451+
452+
if (interface_exists(DriverResult::class)) {
453+
$result = $this->createMock(DriverResult::class);
454+
$result->method('fetchAssociative')->willReturn(false);
455+
456+
if (class_exists(Result::class)) {
457+
$result = new Result($result, $driverConnection);
458+
}
459+
} else {
460+
$result = $this->createMock(ResultStatement::class);
461+
$result->method('fetch')->willReturn(false);
462+
}
463+
464+
$driverConnection
465+
->expects($this->once())
466+
->method('executeQuery')
467+
->with($expectedSql)
468+
->willReturn($result)
469+
;
470+
471+
$connection = new Connection([], $driverConnection);
472+
$connection->findAll(50);
473+
}
474+
475+
public function provideFindAllSqlGeneratedByPlatform(): iterable
476+
{
477+
yield 'MySQL' => [
478+
new MySQL57Platform(),
479+
'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',
480+
];
481+
482+
yield 'SQL Server' => [
483+
new SQLServer2012Platform(),
484+
'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',
485+
];
486+
487+
yield 'Oracle' => [
488+
new OraclePlatform(),
489+
'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',
490+
];
491+
}
440492
}

src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ public function get(): ?array
171171
->orderBy('available_at', 'ASC')
172172
->setMaxResults(1);
173173

174+
if ($this->driverConnection->getDatabasePlatform() instanceof OraclePlatform) {
175+
$query->select('m.id');
176+
}
177+
174178
// Append pessimistic write lock to FROM clause if db platform supports it
175179
$sql = $query->getSQL();
176180
if (($fromPart = $query->getQueryPart('from')) &&
@@ -187,18 +191,9 @@ public function get(): ?array
187191

188192
// Wrap the rownum query in a sub-query to allow writelocks without ORA-02014 error
189193
if ($this->driverConnection->getDatabasePlatform() instanceof OraclePlatform) {
190-
$sql = str_replace('SELECT a.* FROM', 'SELECT a.id FROM', $sql);
191-
192-
$wrappedQuery = $this->driverConnection->createQueryBuilder()
193-
->select(
194-
'w.id AS "id", w.body AS "body", w.headers AS "headers", w.queue_name AS "queue_name", '.
195-
'w.created_at AS "created_at", w.available_at AS "available_at", '.
196-
'w.delivered_at AS "delivered_at"'
197-
)
198-
->from($this->configuration['table_name'], 'w')
199-
->where('w.id IN('.$sql.')');
200-
201-
$sql = $wrappedQuery->getSQL();
194+
$sql = $this->createQueryBuilder('w')
195+
->where('w.id IN ('.str_replace('SELECT a.* FROM', 'SELECT a.id FROM', $sql).')')
196+
->getSQL();
202197
}
203198

204199
// use SELECT ... FOR UPDATE to lock table
@@ -287,7 +282,7 @@ public function setup(): void
287282
public function getMessageCount(): int
288283
{
289284
$queryBuilder = $this->createAvailableMessagesQueryBuilder()
290-
->select('COUNT(m.id) as message_count')
285+
->select('COUNT(m.id) AS message_count')
291286
->setMaxResults(1);
292287

293288
$stmt = $this->executeQuery($queryBuilder->getSQL(), $queryBuilder->getParameters(), $queryBuilder->getParameterTypes());
@@ -298,6 +293,7 @@ public function getMessageCount(): int
298293
public function findAll(int $limit = null): array
299294
{
300295
$queryBuilder = $this->createAvailableMessagesQueryBuilder();
296+
301297
if (null !== $limit) {
302298
$queryBuilder->setMaxResults($limit);
303299
}
@@ -365,11 +361,25 @@ private function createAvailableMessagesQueryBuilder(): QueryBuilder
365361
]);
366362
}
367363

368-
private function createQueryBuilder(): QueryBuilder
364+
private function createQueryBuilder(string $alias = 'm'): QueryBuilder
369365
{
370-
return $this->driverConnection->createQueryBuilder()
371-
->select('m.*')
372-
->from($this->configuration['table_name'], 'm');
366+
$queryBuilder = $this->driverConnection->createQueryBuilder()
367+
->from($this->configuration['table_name'], $alias);
368+
369+
$alias .= '.';
370+
371+
if (!$this->driverConnection->getDatabasePlatform() instanceof OraclePlatform) {
372+
return $queryBuilder->select($alias.'*');
373+
}
374+
375+
// Oracle databases use UPPER CASE on tables and column identifiers.
376+
// Column alias is added to force the result to be lowercase even when the actual field is all caps.
377+
378+
return $queryBuilder->select(str_replace(', ', ', '.$alias,
379+
$alias.'id AS "id", body AS "body", headers AS "headers", queue_name AS "queue_name", '.
380+
'created_at AS "created_at", available_at AS "available_at", '.
381+
'delivered_at AS "delivered_at"'
382+
));
373383
}
374384

375385
private function executeQuery(string $sql, array $parameters = [], array $types = [])

0 commit comments

Comments
 (0)
0