61 'queryLogger' =>
MediaWiki\Logger\LoggerFactory::getInstance(
'DBQuery' ),
63 'chronologyCallback' =>
function ()
use ( &
$called ) {
68 $ld = DatabaseDomain::newFromId( $lb->getLocalDomainID() );
69 $this->assertEquals(
$wgDBname, $ld->getDatabase(),
'local domain DB set' );
70 $this->assertEquals( $this->
dbPrefix(), $ld->getTablePrefix(),
'local domain prefix set' );
71 $this->assertSame(
'my_test_wiki', $lb->resolveDomainID(
'my_test_wiki' ) );
78 $this->assertTrue( $dbw->getLBInfo(
'master' ),
'master shows as master' );
79 $this->assertTrue( $dbw->getFlag(
$dbw::DBO_TRX ),
"DBO_TRX set on master" );
83 $this->assertTrue(
$dbr->getLBInfo(
'master' ),
'DB_REPLICA also gets the master' );
86 if ( !$lb->getServerAttributes( $lb->getWriterIndex() )[$dbw::ATTR_DB_LEVEL_LOCKING] ) {
87 $dbwAuto = $lb->getConnection(
DB_MASTER, [],
false, $lb::CONN_TRX_AUTOCOMMIT );
89 $dbwAuto->getFlag(
$dbw::DBO_TRX ),
"No DBO_TRX with CONN_TRX_AUTOCOMMIT" );
90 $this->assertTrue( $dbw->getFlag(
$dbw::DBO_TRX ),
"DBO_TRX still set on master" );
91 $this->assertNotEquals(
92 $dbw, $dbwAuto,
"CONN_TRX_AUTOCOMMIT uses separate connection" );
94 $dbrAuto = $lb->getConnection(
DB_REPLICA, [],
false, $lb::CONN_TRX_AUTOCOMMIT );
96 $dbrAuto->getFlag(
$dbw::DBO_TRX ),
"No DBO_TRX with CONN_TRX_AUTOCOMMIT" );
97 $this->assertTrue(
$dbr->getFlag(
$dbw::DBO_TRX ),
"DBO_TRX still set on replica" );
98 $this->assertNotEquals(
99 $dbr, $dbrAuto,
"CONN_TRX_AUTOCOMMIT uses separate connection" );
101 $dbwAuto2 = $lb->getConnection(
DB_MASTER, [],
false, $lb::CONN_TRX_AUTOCOMMIT );
102 $this->assertEquals( $dbwAuto2, $dbwAuto,
"CONN_TRX_AUTOCOMMIT reuses connections" );
137 'servers' => $servers,
139 'queryLogger' =>
MediaWiki\Logger\LoggerFactory::getInstance(
'DBQuery' ),
144 $this->assertTrue( $dbw->getLBInfo(
'master' ),
'master shows as master' );
147 $dbw->getLBInfo(
'clusterMasterHost' ),
148 'cluster master set' );
149 $this->assertTrue( $dbw->getFlag(
$dbw::DBO_TRX ),
"DBO_TRX set on master" );
153 $this->assertTrue(
$dbr->getLBInfo(
'replica' ),
'replica shows as replica' );
156 $dbr->getLBInfo(
'clusterMasterHost' ),
157 'cluster master set' );
161 if ( !$lb->getServerAttributes( $lb->getWriterIndex() )[$dbw::ATTR_DB_LEVEL_LOCKING] ) {
162 $dbwAuto = $lb->getConnection(
DB_MASTER, [],
false, $lb::CONN_TRX_AUTOCOMMIT );
164 $dbwAuto->getFlag(
$dbw::DBO_TRX ),
"No DBO_TRX with CONN_TRX_AUTOCOMMIT" );
165 $this->assertTrue( $dbw->getFlag(
$dbw::DBO_TRX ),
"DBO_TRX still set on master" );
166 $this->assertNotEquals(
167 $dbw, $dbwAuto,
"CONN_TRX_AUTOCOMMIT uses separate connection" );
169 $dbrAuto = $lb->getConnection(
DB_REPLICA, [],
false, $lb::CONN_TRX_AUTOCOMMIT );
171 $dbrAuto->getFlag(
$dbw::DBO_TRX ),
"No DBO_TRX with CONN_TRX_AUTOCOMMIT" );
172 $this->assertTrue(
$dbr->getFlag(
$dbw::DBO_TRX ),
"DBO_TRX still set on replica" );
173 $this->assertNotEquals(
174 $dbr, $dbrAuto,
"CONN_TRX_AUTOCOMMIT uses separate connection" );
176 $dbwAuto2 = $lb->getConnection(
DB_MASTER, [],
false, $lb::CONN_TRX_AUTOCOMMIT );
177 $this->assertEquals( $dbwAuto2, $dbwAuto,
"CONN_TRX_AUTOCOMMIT reuses connections" );
185 $db->
delete(
'some_table', [
'id' => 57634126 ], __METHOD__ );
186 $this->fail(
'Write operation should have failed!' );
189 $constraint =
new PHPUnit_Framework_Constraint_StringContains(
'Write operation' );
191 if ( !$constraint->evaluate( $ex->getMessage(),
'',
true ) ) {
203 $useAtomicSection = in_array(
$db->
getType(), [
'sqlite',
'postgres',
'mssql' ],
true );
206 $this->assertNotEquals( $db::STATUS_TRX_ERROR,
$db->
trxStatus() );
208 if ( $useAtomicSection ) {
212 $this->assertNotSame(
214 $db->
query(
"CREATE TABLE $table (id INT, time INT)", __METHOD__ ),
217 $this->assertNotEquals( $db::STATUS_TRX_ERROR,
$db->
trxStatus() );
218 $this->assertNotSame(
220 $db->
query(
"DELETE FROM $table WHERE id=57634126", __METHOD__ ),
223 $this->assertNotEquals( $db::STATUS_TRX_ERROR,
$db->
trxStatus() );
225 if ( !$useAtomicSection ) {
231 $this->assertNotEquals( $db::STATUS_TRX_ERROR,
$db->
trxStatus() );
238 'dbname' =>
'my_unittest_wiki',
239 'tablePrefix' =>
'unittest_',
241 'dbDirectory' =>
"some_directory",
247 'servers' => $servers,
248 'localDomain' =>
new DatabaseDomain(
'my_unittest_wiki',
null,
'unittest_' ),
252 $this->assertTrue( $lb->getServerAttributes( 0 )[Database::ATTR_DB_LEVEL_LOCKING] );
257 'user' =>
'wikiuser',
258 'password' =>
'none',
259 'dbname' =>
'my_unittest_wiki',
260 'tablePrefix' =>
'unittest_',
266 'user' =>
'wikiuser',
267 'password' =>
'none',
268 'dbname' =>
'my_unittest_wiki',
269 'tablePrefix' =>
'unittest_',
276 'servers' => $servers,
277 'localDomain' =>
new DatabaseDomain(
'my_unittest_wiki',
null,
'unittest_' ),
281 $this->assertFalse( $lb->getServerAttributes( 1 )[Database::ATTR_DB_LEVEL_LOCKING] );
296 $i = $lb->getWriterIndex();
297 $this->assertEquals(
null, $lb->getAnyOpenConnection( $i ) );
298 $conn1 = $lb->getConnection( $i );
299 $this->assertNotEquals(
null, $conn1 );
300 $this->assertEquals( $conn1, $lb->getAnyOpenConnection( $i ) );
301 $conn2 = $lb->getConnection( $i, [],
false, $lb::CONN_TRX_AUTOCOMMIT );
302 $this->assertNotEquals(
null, $conn2 );
303 if ( $lb->getServerAttributes( $i )[Database::ATTR_DB_LEVEL_LOCKING] ) {
304 $this->assertEquals(
null,
305 $lb->getAnyOpenConnection( $i, $lb::CONN_TRX_AUTOCOMMIT ) );
306 $this->assertEquals( $conn1,
308 $i, [],
false, $lb::CONN_TRX_AUTOCOMMIT ), $lb::CONN_TRX_AUTOCOMMIT );
310 $this->assertEquals( $conn2,
311 $lb->getAnyOpenConnection( $i, $lb::CONN_TRX_AUTOCOMMIT ) );
312 $this->assertEquals( $conn2,
313 $lb->getConnection( $i, [],
false, $lb::CONN_TRX_AUTOCOMMIT ) );
315 $conn2->startAtomic( __METHOD__ );
317 $lb->getConnection( $i, [],
false, $lb::CONN_TRX_AUTOCOMMIT );
318 $conn2->endAtomic( __METHOD__ );
319 $this->fail(
"No exception thrown." );
320 }
catch ( DBUnexpectedError
$e ) {
322 'Wikimedia\Rdbms\LoadBalancer::openConnection: ' .
323 'CONN_TRX_AUTOCOMMIT handle has a transaction.',
327 $conn2->endAtomic( __METHOD__ );
351 'servers' => $servers,
355 $conn1 = $lb->openConnection( $lb->getWriterIndex(),
false );
356 $conn2 = $lb->openConnection( $lb->getWriterIndex(),
'' );
359 $lb->forEachOpenMasterConnection(
function ()
use ( &$count ) {
362 $this->assertEquals( 2, $count,
'Connection handle count' );
365 $lb->setTransactionListener(
'test-listener',
function ()
use ( &$tlCalls ) {
369 $lb->beginMasterChanges( __METHOD__ );
370 $bc = array_fill_keys( [
'a',
'b',
'c',
'd' ], 0 );
371 $conn1->onTransactionPreCommitOrIdle(
function ()
use ( &$bc, $conn1, $conn2 ) {
373 $conn2->onTransactionPreCommitOrIdle(
function ()
use ( &$bc, $conn1, $conn2 ) {
375 $conn1->onTransactionPreCommitOrIdle(
function ()
use ( &$bc, $conn1, $conn2 ) {
377 $conn1->onTransactionPreCommitOrIdle(
function ()
use ( &$bc, $conn1, $conn2 ) {
383 $lb->finalizeMasterChanges();
384 $lb->approveMasterChanges( [] );
385 $lb->commitMasterChanges( __METHOD__ );
386 $lb->runMasterTransactionIdleCallbacks();
387 $lb->runMasterTransactionListenerCallbacks();
389 $this->assertEquals( array_fill_keys( [
'a',
'b',
'c',
'd' ], 1 ), $bc );
390 $this->assertEquals( 2, $tlCalls );
393 $lb->beginMasterChanges( __METHOD__ );
394 $ac = array_fill_keys( [
'a',
'b',
'c',
'd' ], 0 );
395 $conn1->onTransactionCommitOrIdle(
function ()
use ( &$ac, $conn1, $conn2 ) {
397 $conn2->onTransactionCommitOrIdle(
function ()
use ( &$ac, $conn1, $conn2 ) {
399 $conn1->onTransactionCommitOrIdle(
function ()
use ( &$ac, $conn1, $conn2 ) {
401 $conn1->onTransactionCommitOrIdle(
function ()
use ( &$ac, $conn1, $conn2 ) {
407 $lb->finalizeMasterChanges();
408 $lb->approveMasterChanges( [] );
409 $lb->commitMasterChanges( __METHOD__ );
410 $lb->runMasterTransactionIdleCallbacks();
411 $lb->runMasterTransactionListenerCallbacks();
413 $this->assertEquals( array_fill_keys( [
'a',
'b',
'c',
'd' ], 1 ), $ac );
414 $this->assertEquals( 2, $tlCalls );