Unverified Commit a05f4493 authored by Grégoire Paris's avatar Grégoire Paris Committed by GitHub

Merge pull request #4083 from greg0ire/remove-master-slave

Remove MasterSlaveConnection
parents a22303c1 794514b9
# Upgrade to 3.0 # Upgrade to 3.0
## Removed `MasterSlaveConnection`
This class was deprecated in favor of `PrimaryReadReplicaConnection`
## Removed `Portability\Connection::PORTABILITY_{PLATFORM}` constants` ## Removed `Portability\Connection::PORTABILITY_{PLATFORM}` constants`
The platform-specific portability constants were internal implementation details which are longer relevant. The platform-specific portability constants were internal implementation details which are longer relevant.
......
<?php
namespace Doctrine\DBAL\Connections;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Driver;
use InvalidArgumentException;
use function sprintf;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
* @deprecated Use PrimaryReadReplicaConnection instead
*/
class MasterSlaveConnection extends PrimaryReadReplicaConnection
{
/**
* Creates Primary Replica Connection.
*
* @param mixed[] $params
*
* @throws InvalidArgumentException
*/
public function __construct(array $params, Driver $driver, ?Configuration $config = null, ?EventManager $eventManager = null)
{
$this->deprecated(self::class, PrimaryReadReplicaConnection::class);
if (isset($params['master'])) {
$this->deprecated('Params key "master"', '"primary"');
$params['primary'] = $params['master'];
unset($params['master']);
}
if (isset($params['slaves'])) {
$this->deprecated('Params key "slaves"', '"replica"');
$params['replica'] = $params['slaves'];
unset($params['slaves']);
}
if (isset($params['keepSlave'])) {
$this->deprecated('Params key "keepSlave"', '"keepReplica"');
$params['keepReplica'] = $params['keepSlave'];
unset($params['keepSlave']);
}
parent::__construct($params, $driver, $config, $eventManager);
}
/**
* Checks if the connection is currently towards the primary or not.
*/
public function isConnectedToMaster(): bool
{
$this->deprecated('isConnectedtoMaster()', 'isConnectedToPrimary()');
return $this->isConnectedToPrimary();
}
/**
* @param string|null $connectionName
*
* @return bool
*/
public function connect($connectionName = null)
{
if ($connectionName === 'master') {
$connectionName = 'primary';
$this->deprecated('connect("master")', 'ensureConnectedToPrimary()');
}
if ($connectionName === 'slave') {
$connectionName = 'replica';
$this->deprecated('connect("slave")', 'ensureConnectedToReplica()');
}
return $this->performConnect($connectionName);
}
private function deprecated(string $thing, string $instead): void
{
@trigger_error(
sprintf(
'%s is deprecated since doctrine/dbal 2.11 and will be removed in 3.0, use %s instead.',
$thing,
$instead
),
E_USER_DEPRECATED
);
}
}
...@@ -137,18 +137,6 @@ final class DriverManager ...@@ -137,18 +137,6 @@ final class DriverManager
$params = self::parseDatabaseUrl($params); $params = self::parseDatabaseUrl($params);
// @todo: deprecated, notice thrown by connection constructor
if (isset($params['master'])) {
$params['master'] = self::parseDatabaseUrl($params['master']);
}
// @todo: deprecated, notice thrown by connection constructor
if (isset($params['slaves'])) {
foreach ($params['slaves'] as $key => $slaveParams) {
$params['slaves'][$key] = self::parseDatabaseUrl($slaveParams);
}
}
// URL support for PrimaryReplicaConnection // URL support for PrimaryReplicaConnection
if (isset($params['primary'])) { if (isset($params['primary'])) {
$params['primary'] = self::parseDatabaseUrl($params['primary']); $params['primary'] = self::parseDatabaseUrl($params['primary']);
......
<?php
namespace Doctrine\DBAL\Tests\Functional;
use Doctrine\DBAL\Connections\MasterSlaveConnection;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Tests\FunctionalTestCase;
use Throwable;
use function array_change_key_case;
use function sprintf;
use function strlen;
use function strtolower;
use function substr;
use const CASE_LOWER;
/**
* @group DBAL-20
*/
class MasterSlaveConnectionTest extends FunctionalTestCase
{
protected function setUp(): void
{
parent::setUp();
$platformName = $this->connection->getDatabasePlatform()->getName();
// This is a MySQL specific test, skip other vendors.
if ($platformName !== 'mysql') {
self::markTestSkipped(sprintf('Test does not work on %s.', $platformName));
}
try {
$table = new Table('master_slave_table');
$table->addColumn('test_int', 'integer');
$table->setPrimaryKey(['test_int']);
$sm = $this->connection->getSchemaManager();
$sm->createTable($table);
} catch (Throwable $e) {
}
$this->connection->executeUpdate('DELETE FROM master_slave_table');
$this->connection->insert('master_slave_table', ['test_int' => 1]);
}
private function createMasterSlaveConnection(bool $keepSlave = false): MasterSlaveConnection
{
return DriverManager::getConnection($this->createMasterSlaveConnectionParams($keepSlave));
}
/**
* @return mixed[]
*/
private function createMasterSlaveConnectionParams(bool $keepSlave = false): array
{
$params = $this->connection->getParams();
$params['master'] = $params;
$params['slaves'] = [$params, $params];
$params['keepSlave'] = $keepSlave;
$params['wrapperClass'] = MasterSlaveConnection::class;
return $params;
}
public function testInheritCharsetFromMaster(): void
{
$charsets = [
'utf8',
'latin1',
];
foreach ($charsets as $charset) {
$params = $this->createMasterSlaveConnectionParams();
$params['master']['charset'] = $charset;
foreach ($params['slaves'] as $index => $slaveParams) {
if (! isset($slaveParams['charset'])) {
continue;
}
unset($params['slaves'][$index]['charset']);
}
$conn = DriverManager::getConnection($params);
self::assertInstanceOf(MasterSlaveConnection::class, $conn);
$conn->connect('slave');
self::assertFalse($conn->isConnectedToMaster());
$clientCharset = $conn->fetchOne('select @@character_set_client as c');
self::assertSame(
$charset,
substr(strtolower($clientCharset), 0, strlen($charset))
);
}
}
public function testMasterOnConnect(): void
{
$conn = $this->createMasterSlaveConnection();
self::assertFalse($conn->isConnectedToMaster());
$conn->connect('slave');
self::assertFalse($conn->isConnectedToMaster());
$conn->connect('master');
self::assertTrue($conn->isConnectedToMaster());
}
public function testNoMasterOnExecuteQuery(): void
{
$conn = $this->createMasterSlaveConnection();
$sql = 'SELECT count(*) as num FROM master_slave_table';
$data = $conn->fetchAllAssociative($sql);
$data[0] = array_change_key_case($data[0], CASE_LOWER);
self::assertEquals(1, $data[0]['num']);
self::assertFalse($conn->isConnectedToMaster());
}
public function testMasterOnWriteOperation(): void
{
$conn = $this->createMasterSlaveConnection();
$conn->insert('master_slave_table', ['test_int' => 30]);
self::assertTrue($conn->isConnectedToMaster());
$sql = 'SELECT count(*) as num FROM master_slave_table';
$data = $conn->fetchAllAssociative($sql);
$data[0] = array_change_key_case($data[0], CASE_LOWER);
self::assertEquals(2, $data[0]['num']);
self::assertTrue($conn->isConnectedToMaster());
}
/**
* @group DBAL-335
*/
public function testKeepSlaveBeginTransactionStaysOnMaster(): void
{
$conn = $this->createMasterSlaveConnection($keepSlave = true);
$conn->connect('slave');
$conn->beginTransaction();
$conn->insert('master_slave_table', ['test_int' => 30]);
$conn->commit();
self::assertTrue($conn->isConnectedToMaster());
$conn->connect();
self::assertTrue($conn->isConnectedToMaster());
$conn->connect('slave');
self::assertFalse($conn->isConnectedToMaster());
}
/**
* @group DBAL-335
*/
public function testKeepSlaveInsertStaysOnMaster(): void
{
$conn = $this->createMasterSlaveConnection($keepSlave = true);
$conn->connect('slave');
$conn->insert('master_slave_table', ['test_int' => 30]);
self::assertTrue($conn->isConnectedToMaster());
$conn->connect();
self::assertTrue($conn->isConnectedToMaster());
$conn->connect('slave');
self::assertFalse($conn->isConnectedToMaster());
}
public function testMasterSlaveConnectionCloseAndReconnect(): void
{
$conn = $this->createMasterSlaveConnection();
$conn->connect('master');
self::assertTrue($conn->isConnectedToMaster());
$conn->close();
self::assertFalse($conn->isConnectedToMaster());
$conn->connect('master');
self::assertTrue($conn->isConnectedToMaster());
}
public function testQueryOnMaster(): void
{
$conn = $this->createMasterSlaveConnection();
$query = 'SELECT count(*) as num FROM master_slave_table';
$result = $conn->query($query);
//Query must be executed only on Master
self::assertTrue($conn->isConnectedToMaster());
$data = $result->fetchAllAssociative();
self::assertArrayHasKey(0, $data);
self::assertArrayHasKey('num', $data[0]);
//Could be set in other fetchmodes
self::assertArrayNotHasKey(0, $data[0]);
self::assertEquals(1, $data[0]['num']);
}
public function testQueryOnSlave(): void
{
$conn = $this->createMasterSlaveConnection();
$conn->connect('slave');
$query = 'SELECT count(*) as num FROM master_slave_table';
$result = $conn->query($query);
//Query must be executed only on Master, even when we connect to the slave
self::assertTrue($conn->isConnectedToMaster());
$data = $result->fetchAllAssociative();
self::assertArrayHasKey(0, $data);
self::assertArrayHasKey('num', $data[0]);
//Could be set in other fetchmodes
self::assertArrayNotHasKey(0, $data[0]);
self::assertEquals(1, $data[0]['num']);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment