From 37be09499201804c28a799ad2206b913f857559a Mon Sep 17 00:00:00 2001 From: bill moll Date: Tue, 24 Nov 2020 14:13:56 -0600 Subject: [PATCH] [Messenger] Fix mssql compatibility for doctrine transport. Add logic for locking row for update when the doctrine dbal connection is sqlsrv. This is a quick and dirty solution, but it prevents the need to rewrite the logic due to doctrine dbal limitations. See issue https://github.com/symfony/symfony/issues/39117 --- .../Messenger/Transport/Doctrine/Connection.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php b/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php index 637c7a57ac..ef41dc5f02 100644 --- a/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php +++ b/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php @@ -16,6 +16,7 @@ use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\Result as DriverResult; use Doctrine\DBAL\Exception; use Doctrine\DBAL\Exception\TableNotFoundException; +use Doctrine\DBAL\LockMode; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Result; use Doctrine\DBAL\Schema\Comparator; @@ -161,9 +162,23 @@ class Connection ->orderBy('available_at', 'ASC') ->setMaxResults(1); + // 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); + $sql = str_replace( + sprintf('FROM %s WHERE', $fromClause), + sprintf('FROM %s WHERE', $this->driverConnection->getDatabasePlatform()->appendLockHint($fromClause, LockMode::PESSIMISTIC_WRITE)), + $sql + ); + } + // use SELECT ... FOR UPDATE to lock table $stmt = $this->executeQuery( - $query->getSQL().' '.$this->driverConnection->getDatabasePlatform()->getWriteLockSQL(), + $sql.' '.$this->driverConnection->getDatabasePlatform()->getWriteLockSQL(), $query->getParameters(), $query->getParameterTypes() );