8000 bug #45714 [Messenger] Fix cannot select FOR UPDATE from view on Orac… · symfony/symfony@deb9030 · GitHub
[go: up one dir, main page]

Skip to content

Commit deb9030

Browse files
bug #45714 [Messenger] Fix cannot select FOR UPDATE from view on Oracle (rjd22)
This PR was merged into the 4.4 branch. Discussion ---------- [Messenger] Fix cannot select FOR UPDATE from view on Oracle | Q | A | ------------- | --- | Branch? | 4.4 <!-- see below --> | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #33718 | License | MIT I realize this solution is quite getto. I hope to get some feedback on it so we can solve this oracle issue properly but ATM this is a good starting point to reach a proper solution. For this reason I didn't add tests yet. What happens is that Oracle doesn't like query's that combine ROWNUM and FOR UPDATE. To solve this the query needs to be wrapped in a subquery that limits the results by ID so: ```sql SELECT a.* 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; ``` becomes: ```sql SELECT * FROM messenger_messages WHERE 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; ``` I don't really know another way to solve this better. But feel free to nitpick at my solution. Commits ------- d4a695f [Messenger] Fix cannot select FOR UPDATE from view on Oracle
2 parents f55927a + d4a695f commit deb9030

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Doctrine\DBAL\Exception\TableNotFoundException;
2020
use Doctrine\DBAL\LockMode;
2121
use Doctrine\DBAL\Platforms\MySQLPlatform;
22+
use Doctrine\DBAL\Platforms\OraclePlatform;
2223
use Doctrine\DBAL\Query\QueryBuilder;
2324
use Doctrine\DBAL\Result;
2425
use Doctrine\DBAL\Schema\AbstractSchemaManager;
@@ -187,6 +188,18 @@ public function get(): ?array
187188
);
188189
}
189190

191+
// Wrap the rownum query in a sub-query to allow writelocks without ORA-02014 error
192+
if ($this->driverConnection->getDatabasePlatform() instanceof OraclePlatform) {
193+
$sql = str_replace('SELECT a.* FROM', 'SELECT a.id FROM', $sql);
194+
195+
$wrappedQuery = $this->driverConnection->createQueryBuilder()
196+
->select('w.*')
197+
->from($this->configuration['table_name'], 'w')
198+
->where('w.id IN('.$sql.')');
199+
200+
$sql = $wrappedQuery->getSQL();
201+
}
202+
190203
// use SELECT ... FOR UPDATE to lock table
191204
$stmt = $this->executeQuery(
192205
$sql.' '.$this->driverConnection->getDatabasePlatform()->getWriteLockSQL(),

0 commit comments

Comments
 (0)
0