From 9fb5e61606b4cbd1f688f02d1fbcacc255e288d5 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Sat, 11 Dec 2021 17:02:08 +0100 Subject: [PATCH] Move primary replica connection logic into ORM explicitly. --- lib/Doctrine/ORM/Id/SequenceGenerator.php | 5 +++++ lib/Doctrine/ORM/Id/UuidGenerator.php | 5 +++++ lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php | 5 +++++ lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php | 5 +++++ .../ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php | 5 +++++ lib/Doctrine/ORM/UnitOfWork.php | 7 +++++++ 6 files changed, 32 insertions(+) diff --git a/lib/Doctrine/ORM/Id/SequenceGenerator.php b/lib/Doctrine/ORM/Id/SequenceGenerator.php index b37a366b084..307bcb4cd51 100644 --- a/lib/Doctrine/ORM/Id/SequenceGenerator.php +++ b/lib/Doctrine/ORM/Id/SequenceGenerator.php @@ -4,6 +4,7 @@ namespace Doctrine\ORM\Id; +use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection; use Doctrine\ORM\EntityManager; use Serializable; @@ -57,6 +58,10 @@ public function generate(EntityManager $em, $entity) $conn = $em->getConnection(); $sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName); + if ($conn instanceof PrimaryReadReplicaConnection) { + $conn->ensureConnectedToPrimary(); + } + // Using `query` to force usage of the master server in MasterSlaveConnection $this->_nextValue = (int) $conn->executeQuery($sql)->fetchOne(); $this->_maxValue = $this->_nextValue + $this->_allocationSize; diff --git a/lib/Doctrine/ORM/Id/UuidGenerator.php b/lib/Doctrine/ORM/Id/UuidGenerator.php index f6b87589378..6eca7282bc3 100644 --- a/lib/Doctrine/ORM/Id/UuidGenerator.php +++ b/lib/Doctrine/ORM/Id/UuidGenerator.php @@ -4,6 +4,7 @@ namespace Doctrine\ORM\Id; +use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\Deprecations\Deprecation; use Doctrine\ORM\EntityManager; @@ -42,6 +43,10 @@ public function generate(EntityManager $em, $entity) $conn = $em->getConnection(); $sql = 'SELECT ' . $conn->getDatabasePlatform()->getGuidExpression(); + if ($conn instanceof PrimaryReadReplicaConnection) { + $conn->ensureConnectedToPrimary(); + } + return $conn->executeQuery($sql)->fetchOne(); } } diff --git a/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php b/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php index ddd549f9766..72a0cca3aa1 100644 --- a/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php +++ b/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php @@ -5,6 +5,7 @@ namespace Doctrine\ORM\Query\Exec; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection; use Doctrine\DBAL\Types\Type; use Doctrine\ORM\Query\AST; use Doctrine\ORM\Query\AST\DeleteStatement; @@ -49,6 +50,10 @@ public function __construct(AST\Node $AST, $sqlWalker) $platform = $conn->getDatabasePlatform(); $quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); + if ($conn instanceof PrimaryReadReplicaConnection) { + $conn->ensureConnectedToPrimary(); + } + $primaryClass = $em->getClassMetadata($AST->deleteClause->abstractSchemaName); $primaryDqlAlias = $AST->deleteClause->aliasIdentificationVariable; $rootClass = $em->getClassMetadata($primaryClass->rootEntityName); diff --git a/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php b/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php index 3a445a97c64..9049a4d10f7 100644 --- a/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php +++ b/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php @@ -5,6 +5,7 @@ namespace Doctrine\ORM\Query\Exec; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection; use Doctrine\DBAL\Types\Type; use Doctrine\ORM\Query\AST; use Doctrine\ORM\Query\AST\UpdateStatement; @@ -55,6 +56,10 @@ public function __construct(AST\Node $AST, $sqlWalker) $platform = $conn->getDatabasePlatform(); $quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); + if ($conn instanceof PrimaryReadReplicaConnection) { + $conn->ensureConnectedToPrimary(); + } + $updateClause = $AST->updateClause; $primaryClass = $sqlWalker->getEntityManager()->getClassMetadata($updateClause->abstractSchemaName); $rootClass = $em->getClassMetadata($primaryClass->rootEntityName); diff --git a/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php b/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php index bee136d5cbd..92d49c911e4 100644 --- a/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php +++ b/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php @@ -5,6 +5,7 @@ namespace Doctrine\ORM\Query\Exec; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection; use Doctrine\ORM\Query\AST; use Doctrine\ORM\Query\SqlWalker; @@ -37,6 +38,10 @@ public function __construct(AST\Node $AST, $sqlWalker) */ public function execute(Connection $conn, array $params, array $types) { + if ($conn instanceof PrimaryReadReplicaConnection) { + $conn->ensureConnectedToPrimary(); + } + return $conn->executeStatement($this->_sqlStatements, $params, $types); } } diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 9cb76f4d967..37a199cfbab 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -9,6 +9,7 @@ use Doctrine\Common\Collections\Collection; use Doctrine\Common\EventManager; use Doctrine\Common\Proxy\Proxy; +use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection; use Doctrine\DBAL\LockMode; use Doctrine\Deprecations\Deprecation; use Doctrine\ORM\Cache\Persister\CachedPersister; @@ -338,6 +339,12 @@ public function __construct(EntityManagerInterface $em) */ public function commit($entity = null) { + $connection = $this->em->getConnection(); + + if ($connection instanceof PrimaryReadReplicaConnection) { + $connection->ensureConnectedToPrimary(); + } + // Raise preFlush if ($this->evm->hasListeners(Events::preFlush)) { $this->evm->dispatchEvent(Events::preFlush, new PreFlushEventArgs($this->em));