| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | declare(strict_types=1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | namespace Doctrine\DBAL\Sharding; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | use Doctrine\Common\EventManager; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | use Doctrine\DBAL\Configuration; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | use Doctrine\DBAL\Connection; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | use Doctrine\DBAL\Driver; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | use Doctrine\DBAL\Driver\Connection as DriverConnection; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | use Doctrine\DBAL\Event\ConnectionEventArgs; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | use Doctrine\DBAL\Events; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | use Doctrine\DBAL\Sharding\ShardChoser\ShardChoser; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | use InvalidArgumentException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | use function array_merge; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | use function is_numeric; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | use function is_string; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | use function sprintf; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |  * Sharding implementation that pools many different connections | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |  * internally and serves data from the currently active connection. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |  * The internals of this class are: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |  * - All sharding clients are specified and given a shard-id during | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |  *   configuration. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |  * - By default, the global shard is selected. If no global shard is configured | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |  *   an exception is thrown on access. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |  * - Selecting a shard by distribution value delegates the mapping | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |  *   "distributionValue" => "client" to the ShardChoser interface. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |  * - An exception is thrown if trying to switch shards during an open | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |  *   transaction. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |  * Instantiation through the DriverManager looks like: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |  * @example | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |  * $conn = DriverManager::getConnection(array( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |  *    'wrapperClass' => 'Doctrine\DBAL\Sharding\PoolingShardConnection', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |  *    'driver' => 'pdo_mysql', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |  *    'global' => array('user' => '', 'password' => '', 'host' => '', 'dbname' => ''), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |  *    'shards' => array( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |  *        array('id' => 1, 'user' => 'slave1', 'password', 'host' => '', 'dbname' => ''), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |  *        array('id' => 2, 'user' => 'slave2', 'password', 'host' => '', 'dbname' => ''), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |  *    ), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |  *    'shardChoser' => 'Doctrine\DBAL\Sharding\ShardChoser\MultiTenantShardChoser', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |  * )); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |  * $shardManager = $conn->getShardManager(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |  * $shardManager->selectGlobal(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |  * $shardManager->selectShard($value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  | class PoolingShardConnection extends Connection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |     /** @var DriverConnection[] */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |     private $activeConnections = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |     /** @var string|int|null */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |     private $activeShardId; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |     /** @var mixed[] */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |     private $connectionParameters = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |      * {@inheritDoc} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |      * @throws InvalidArgumentException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 | 407 |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |     public function __construct( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 | 407 |  |         array $params, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 | 329 |  |         Driver $driver, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |         ?Configuration $config = null, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |         ?EventManager $eventManager = null | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 | 403 |  |     ) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 | 277 |  |         if (! isset($params['global'], $params['shards'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |             throw new InvalidArgumentException('Connection Parameters require "global" and "shards" configurations.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 | 401 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 | 399 |  |         if (! isset($params['shardChoser'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |             throw new InvalidArgumentException('Missing Shard Choser configuration "shardChoser".'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 401 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 | 252 |  |         if (is_string($params['shardChoser'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |             $params['shardChoser'] = new $params['shardChoser'](); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 | 399 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |         if (! ($params['shardChoser'] instanceof ShardChoser)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 | 399 |  |             throw new InvalidArgumentException('The "shardChoser" configuration is not a valid instance of Doctrine\DBAL\Sharding\ShardChoser\ShardChoser'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 | 399 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 | 202 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |         $this->connectionParameters[0] = array_merge($params, $params['global']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 | 397 |  |         foreach ($params['shards'] as $shard) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 | 227 |  |             if (! isset($shard['id'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |                 throw new InvalidArgumentException('Missing "id" for one configured shard. Please specify a unique shard-id.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 | 395 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 | 177 |  |             if (! is_numeric($shard['id']) || $shard['id'] < 1) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |                 throw new InvalidArgumentException('Shard Id has to be a non-negative number.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 | 395 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |             if (isset($this->connectionParameters[$shard['id']])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |                 throw new InvalidArgumentException(sprintf('Shard "%s" is duplicated in the configuration.', $shard['id'])); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 | 393 |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 | 393 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |             $this->connectionParameters[$shard['id']] = array_merge($params, $shard); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |         parent::__construct($params, $driver, $config, $eventManager); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 | 127 |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |      * Get active shard id. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 | 127 |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |      * @return string|int|null | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |     public function getActiveShardId() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |         return $this->activeShardId; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 | 393 |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 | 393 |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |      * {@inheritdoc} | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 125 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 126 |  |  |     public function getParams() : array | 
            
                                                                        
                            
            
                                    
            
            
                | 127 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 128 |  |  |         return $this->activeShardId ? $this->connectionParameters[$this->activeShardId] : $this->connectionParameters[0]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 | 77 |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 | 77 |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |      * Connects to a given shard. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 | 77 |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |      * @param string|int|null $shardId | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |      * @throws ShardingException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |     public function connect($shardId = null) : void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 | 52 |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |         if ($shardId === null && $this->_conn) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 | 52 |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 | 52 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |         if ($shardId !== null && $shardId === $this->activeShardId) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |         if ($this->getTransactionNestingLevel() > 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 | 52 |  |             throw new ShardingException('Cannot switch shard when transaction is active.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 | 52 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |         $activeShardId = $this->activeShardId = (int) $shardId; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 | 52 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |         if (isset($this->activeConnections[$activeShardId])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |             $this->_conn = $this->activeConnections[$activeShardId]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 | 27 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |         $this->_conn = $this->activeConnections[$activeShardId] = $this->connectTo($activeShardId); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 | 27 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |         if (! $this->_eventManager->hasListeners(Events::postConnect)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 | 27 |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |         $eventArgs = new ConnectionEventArgs($this); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |         $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |      * Connects to a specific connection. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 | 366 |  |      * @param string|int $shardId | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 | 366 |  |     protected function connectTo($shardId) : DriverConnection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 | 352 |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  |         $params = $this->getParams(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 | 366 |  |         $driverOptions = $params['driverOptions'] ?? []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  |         $connectionParams = $this->connectionParameters[$shardId]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 | 366 |  |         $user     = $connectionParams['user'] ?? ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 | 152 |  |         $password = $connectionParams['password'] ?? ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  |         return $this->_driver->connect($connectionParams, $user, $password, $driverOptions); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 | 366 |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 | 366 |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  |      * @param string|int|null $shardId | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 |  |  |     public function isConnected($shardId = null) : bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 |  |  |         if ($shardId === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 | 366 |  |             return $this->_conn !== null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 | 366 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 | 366 |  |         return isset($this->activeConnections[$shardId]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  |     public function close() : void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  |         $this->_conn             = null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |         $this->activeConnections = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  |         $this->activeShardId     = null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 207 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 208 |  |  |  |