MediaWiki  1.32.0
DatabaseTest.php
Go to the documentation of this file.
1 <?php
2 
9 use Wikimedia\TestingAccessWrapper;
14 
15 class DatabaseTest extends PHPUnit\Framework\TestCase {
16 
17  use MediaWikiCoversValidator;
18 
19  protected function setUp() {
20  $this->db = new DatabaseTestHelper( __CLASS__ . '::' . $this->getName() );
21  }
22 
27  public function testFactory() {
28  $m = Database::NEW_UNCONNECTED; // no-connect mode
29  $p = [ 'host' => 'localhost', 'user' => 'me', 'password' => 'myself', 'dbname' => 'i' ];
30 
31  $this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'mysqli', $p, $m ) );
32  $this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'MySqli', $p, $m ) );
33  $this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'MySQLi', $p, $m ) );
34  $this->assertInstanceOf( DatabasePostgres::class, Database::factory( 'postgres', $p, $m ) );
35  $this->assertInstanceOf( DatabasePostgres::class, Database::factory( 'Postgres', $p, $m ) );
36 
37  $x = $p + [ 'port' => 10000, 'UseWindowsAuth' => false ];
38  $this->assertInstanceOf( DatabaseMssql::class, Database::factory( 'mssql', $x, $m ) );
39 
40  $x = $p + [ 'dbFilePath' => 'some/file.sqlite' ];
41  $this->assertInstanceOf( DatabaseSqlite::class, Database::factory( 'sqlite', $x, $m ) );
42  $x = $p + [ 'dbDirectory' => 'some/file' ];
43  $this->assertInstanceOf( DatabaseSqlite::class, Database::factory( 'sqlite', $x, $m ) );
44  }
45 
46  public static function provideAddQuotes() {
47  return [
48  [ null, 'NULL' ],
49  [ 1234, "'1234'" ],
50  [ 1234.5678, "'1234.5678'" ],
51  [ 'string', "'string'" ],
52  [ 'string\'s cause trouble', "'string\'s cause trouble'" ],
53  ];
54  }
55 
60  public function testAddQuotes( $input, $expected ) {
61  $this->assertEquals( $expected, $this->db->addQuotes( $input ) );
62  }
63 
64  public static function provideTableName() {
65  // Formatting is mostly ignored since addIdentifierQuotes is abstract.
66  // For testing of addIdentifierQuotes, see actual Database subclas tests.
67  return [
68  'local' => [
69  'tablename',
70  'tablename',
71  'quoted',
72  ],
73  'local-raw' => [
74  'tablename',
75  'tablename',
76  'raw',
77  ],
78  'shared' => [
79  'sharedb.tablename',
80  'tablename',
81  'quoted',
82  [ 'dbname' => 'sharedb', 'schema' => null, 'prefix' => '' ],
83  ],
84  'shared-raw' => [
85  'sharedb.tablename',
86  'tablename',
87  'raw',
88  [ 'dbname' => 'sharedb', 'schema' => null, 'prefix' => '' ],
89  ],
90  'shared-prefix' => [
91  'sharedb.sh_tablename',
92  'tablename',
93  'quoted',
94  [ 'dbname' => 'sharedb', 'schema' => null, 'prefix' => 'sh_' ],
95  ],
96  'shared-prefix-raw' => [
97  'sharedb.sh_tablename',
98  'tablename',
99  'raw',
100  [ 'dbname' => 'sharedb', 'schema' => null, 'prefix' => 'sh_' ],
101  ],
102  'foreign' => [
103  'databasename.tablename',
104  'databasename.tablename',
105  'quoted',
106  ],
107  'foreign-raw' => [
108  'databasename.tablename',
109  'databasename.tablename',
110  'raw',
111  ],
112  ];
113  }
114 
119  public function testTableName( $expected, $table, $format, array $alias = null ) {
120  if ( $alias ) {
121  $this->db->setTableAliases( [ $table => $alias ] );
122  }
123  $this->assertEquals(
124  $expected,
125  $this->db->tableName( $table, $format ?: 'quoted' )
126  );
127  }
128 
130  return [
131  'one-element array' => [
132  [ 'table' ], [], 'table '
133  ],
134  'comma join' => [
135  [ 'table1', 'table2' ], [], 'table1,table2 '
136  ],
137  'real join' => [
138  [ 'table1', 'table2' ],
139  [ 'table2' => [ 'LEFT JOIN', 't1_id = t2_id' ] ],
140  'table1 LEFT JOIN table2 ON ((t1_id = t2_id))'
141  ],
142  'real join with multiple conditionals' => [
143  [ 'table1', 'table2' ],
144  [ 'table2' => [ 'LEFT JOIN', [ 't1_id = t2_id', 't2_x = \'X\'' ] ] ],
145  'table1 LEFT JOIN table2 ON ((t1_id = t2_id) AND (t2_x = \'X\'))'
146  ],
147  'join with parenthesized group' => [
148  [ 'table1', 'n' => [ 'table2', 'table3' ] ],
149  [
150  'table3' => [ 'JOIN', 't2_id = t3_id' ],
151  'n' => [ 'LEFT JOIN', 't1_id = t2_id' ],
152  ],
153  'table1 LEFT JOIN (table2 JOIN table3 ON ((t2_id = t3_id))) ON ((t1_id = t2_id))'
154  ],
155  'join with degenerate parenthesized group' => [
156  [ 'table1', 'n' => [ 't2' => 'table2' ] ],
157  [
158  'n' => [ 'LEFT JOIN', 't1_id = t2_id' ],
159  ],
160  'table1 LEFT JOIN table2 t2 ON ((t1_id = t2_id))'
161  ],
162  ];
163  }
164 
169  public function testTableNamesWithIndexClauseOrJOIN( $tables, $join_conds, $expect ) {
170  $clause = TestingAccessWrapper::newFromObject( $this->db )
171  ->tableNamesWithIndexClauseOrJOIN( $tables, [], [], $join_conds );
172  $this->assertSame( $expect, $clause );
173  }
174 
179  public function testTransactionIdle() {
180  $db = $this->db;
181 
182  $db->clearFlag( DBO_TRX );
183  $called = false;
184  $flagSet = null;
185  $callback = function ( $trigger, IDatabase $db ) use ( &$flagSet, &$called ) {
186  $called = true;
187  $flagSet = $db->getFlag( DBO_TRX );
188  };
189 
190  $db->onTransactionCommitOrIdle( $callback, __METHOD__ );
191  $this->assertTrue( $called, 'Callback reached' );
192  $this->assertFalse( $flagSet, 'DBO_TRX off in callback' );
193  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX still default' );
194 
195  $flagSet = null;
196  $called = false;
197  $db->startAtomic( __METHOD__ );
198  $db->onTransactionCommitOrIdle( $callback, __METHOD__ );
199  $this->assertFalse( $called, 'Callback not reached during TRX' );
200  $db->endAtomic( __METHOD__ );
201 
202  $this->assertTrue( $called, 'Callback reached after COMMIT' );
203  $this->assertFalse( $flagSet, 'DBO_TRX off in callback' );
204  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX restored to default' );
205 
206  $db->clearFlag( DBO_TRX );
207  $db->onTransactionCommitOrIdle(
208  function ( $trigger, IDatabase $db ) {
209  $db->setFlag( DBO_TRX );
210  },
211  __METHOD__
212  );
213  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX restored to default' );
214  }
215 
220  public function testTransactionIdle_TRX() {
221  $db = $this->getMockDB( [ 'isOpen', 'ping', 'getDBname' ] );
222  $db->method( 'isOpen' )->willReturn( true );
223  $db->method( 'ping' )->willReturn( true );
224  $db->method( 'getDBname' )->willReturn( '' );
225  $db->setFlag( DBO_TRX );
226 
227  $lbFactory = LBFactorySingle::newFromConnection( $db );
228  // Ask for the connection so that LB sets internal state
229  // about this connection being the master connection
230  $lb = $lbFactory->getMainLB();
231  $conn = $lb->openConnection( $lb->getWriterIndex() );
232  $this->assertSame( $db, $conn, 'Same DB instance' );
233  $this->assertTrue( $db->getFlag( DBO_TRX ), 'DBO_TRX is set' );
234 
235  $called = false;
236  $flagSet = null;
237  $callback = function () use ( $db, &$flagSet, &$called ) {
238  $called = true;
239  $flagSet = $db->getFlag( DBO_TRX );
240  };
241 
242  $db->onTransactionCommitOrIdle( $callback, __METHOD__ );
243  $this->assertTrue( $called, 'Called when idle if DBO_TRX is set' );
244  $this->assertFalse( $flagSet, 'DBO_TRX off in callback' );
245  $this->assertTrue( $db->getFlag( DBO_TRX ), 'DBO_TRX still default' );
246 
247  $called = false;
248  $lbFactory->beginMasterChanges( __METHOD__ );
249  $db->onTransactionCommitOrIdle( $callback, __METHOD__ );
250  $this->assertFalse( $called, 'Not called when lb-transaction is active' );
251 
252  $lbFactory->commitMasterChanges( __METHOD__ );
253  $this->assertTrue( $called, 'Called when lb-transaction is committed' );
254 
255  $called = false;
256  $lbFactory->beginMasterChanges( __METHOD__ );
257  $db->onTransactionCommitOrIdle( $callback, __METHOD__ );
258  $this->assertFalse( $called, 'Not called when lb-transaction is active' );
259 
260  $lbFactory->rollbackMasterChanges( __METHOD__ );
261  $this->assertFalse( $called, 'Not called when lb-transaction is rolled back' );
262 
263  $lbFactory->commitMasterChanges( __METHOD__ );
264  $this->assertFalse( $called, 'Not called in next round commit' );
265 
266  $db->setFlag( DBO_TRX );
267  try {
268  $db->onTransactionCommitOrIdle( function () {
269  throw new RuntimeException( 'test' );
270  } );
271  $this->fail( "Exception not thrown" );
272  } catch ( RuntimeException $e ) {
273  $this->assertTrue( $db->getFlag( DBO_TRX ) );
274  }
275  }
276 
281  public function testTransactionPreCommitOrIdle() {
282  $db = $this->getMockDB( [ 'isOpen' ] );
283  $db->method( 'isOpen' )->willReturn( true );
284  $db->clearFlag( DBO_TRX );
285 
286  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX is not set' );
287 
288  $called = false;
289  $db->onTransactionPreCommitOrIdle(
290  function ( IDatabase $db ) use ( &$called ) {
291  $called = true;
292  },
293  __METHOD__
294  );
295  $this->assertTrue( $called, 'Called when idle' );
296 
297  $db->begin( __METHOD__ );
298  $called = false;
300  function ( IDatabase $db ) use ( &$called ) {
301  $called = true;
302  },
303  __METHOD__
304  );
305  $this->assertFalse( $called, 'Not called when transaction is active' );
306  $db->commit( __METHOD__ );
307  $this->assertTrue( $called, 'Called when transaction is committed' );
308  }
309 
315  $db = $this->getMockDB( [ 'isOpen', 'ping', 'getDBname' ] );
316  $db->method( 'isOpen' )->willReturn( true );
317  $db->method( 'ping' )->willReturn( true );
318  $db->method( 'getDBname' )->willReturn( 'unittest' );
319  $db->setFlag( DBO_TRX );
320 
321  $lbFactory = LBFactorySingle::newFromConnection( $db );
322  // Ask for the connection so that LB sets internal state
323  // about this connection being the master connection
324  $lb = $lbFactory->getMainLB();
325  $conn = $lb->openConnection( $lb->getWriterIndex() );
326  $this->assertSame( $db, $conn, 'Same DB instance' );
327 
328  $this->assertFalse( $lb->hasMasterChanges() );
329  $this->assertTrue( $db->getFlag( DBO_TRX ), 'DBO_TRX is set' );
330  $called = false;
331  $callback = function ( IDatabase $db ) use ( &$called ) {
332  $called = true;
333  };
334  $db->onTransactionPreCommitOrIdle( $callback, __METHOD__ );
335  $this->assertTrue( $called, 'Called when idle if DBO_TRX is set' );
336  $called = false;
337  $lbFactory->commitMasterChanges();
338  $this->assertFalse( $called );
339 
340  $called = false;
341  $lbFactory->beginMasterChanges( __METHOD__ );
342  $db->onTransactionPreCommitOrIdle( $callback, __METHOD__ );
343  $this->assertFalse( $called, 'Not called when lb-transaction is active' );
344  $lbFactory->commitMasterChanges( __METHOD__ );
345  $this->assertTrue( $called, 'Called when lb-transaction is committed' );
346 
347  $called = false;
348  $lbFactory->beginMasterChanges( __METHOD__ );
349  $db->onTransactionPreCommitOrIdle( $callback, __METHOD__ );
350  $this->assertFalse( $called, 'Not called when lb-transaction is active' );
351 
352  $lbFactory->rollbackMasterChanges( __METHOD__ );
353  $this->assertFalse( $called, 'Not called when lb-transaction is rolled back' );
354 
355  $lbFactory->commitMasterChanges( __METHOD__ );
356  $this->assertFalse( $called, 'Not called in next round commit' );
357  }
358 
363  public function testTransactionResolution() {
364  $db = $this->db;
365 
366  $db->clearFlag( DBO_TRX );
367  $db->begin( __METHOD__ );
368  $called = false;
369  $db->onTransactionResolution( function ( $trigger, IDatabase $db ) use ( &$called ) {
370  $called = true;
371  $db->setFlag( DBO_TRX );
372  } );
373  $db->commit( __METHOD__ );
374  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX restored to default' );
375  $this->assertTrue( $called, 'Callback reached' );
376 
377  $db->clearFlag( DBO_TRX );
378  $db->begin( __METHOD__ );
379  $called = false;
380  $db->onTransactionResolution( function ( $trigger, IDatabase $db ) use ( &$called ) {
381  $called = true;
382  $db->setFlag( DBO_TRX );
383  } );
384  $db->rollback( __METHOD__ );
385  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX restored to default' );
386  $this->assertTrue( $called, 'Callback reached' );
387  }
388 
392  public function testTransactionListener() {
393  $db = $this->db;
394 
395  $db->setTransactionListener( 'ping', function () use ( $db, &$called ) {
396  $called = true;
397  } );
398 
399  $called = false;
400  $db->begin( __METHOD__ );
401  $db->commit( __METHOD__ );
402  $this->assertTrue( $called, 'Callback reached' );
403 
404  $called = false;
405  $db->begin( __METHOD__ );
406  $db->commit( __METHOD__ );
407  $this->assertTrue( $called, 'Callback still reached' );
408 
409  $called = false;
410  $db->begin( __METHOD__ );
411  $db->rollback( __METHOD__ );
412  $this->assertTrue( $called, 'Callback reached' );
413 
414  $db->setTransactionListener( 'ping', null );
415  $called = false;
416  $db->begin( __METHOD__ );
417  $db->commit( __METHOD__ );
418  $this->assertFalse( $called, 'Callback not reached' );
419  }
420 
430  private function getMockDB( $methods = [] ) {
431  static $abstractMethods = [
432  'fetchAffectedRowCount',
433  'closeConnection',
434  'dataSeek',
435  'doQuery',
436  'fetchObject', 'fetchRow',
437  'fieldInfo', 'fieldName',
438  'getSoftwareLink', 'getServerVersion',
439  'getType',
440  'indexInfo',
441  'insertId',
442  'lastError', 'lastErrno',
443  'numFields', 'numRows',
444  'open',
445  'strencode',
446  'tableExists'
447  ];
448  $db = $this->getMockBuilder( Database::class )
449  ->disableOriginalConstructor()
450  ->setMethods( array_values( array_unique( array_merge(
451  $abstractMethods,
452  $methods
453  ) ) ) )
454  ->getMock();
455  $wdb = TestingAccessWrapper::newFromObject( $db );
456  $wdb->trxProfiler = new TransactionProfiler();
457  $wdb->connLogger = new \Psr\Log\NullLogger();
458  $wdb->queryLogger = new \Psr\Log\NullLogger();
459  $wdb->currentDomain = DatabaseDomain::newUnspecified();
460  return $db;
461  }
462 
466  public function testFlushSnapshot() {
467  $db = $this->getMockDB( [ 'isOpen' ] );
468  $db->method( 'isOpen' )->willReturn( true );
469 
470  $db->flushSnapshot( __METHOD__ ); // ok
471  $db->flushSnapshot( __METHOD__ ); // ok
472 
473  $db->setFlag( DBO_TRX, $db::REMEMBER_PRIOR );
474  $db->query( 'SELECT 1', __METHOD__ );
475  $this->assertTrue( (bool)$db->trxLevel(), "Transaction started." );
476  $db->flushSnapshot( __METHOD__ ); // ok
477  $db->restoreFlags( $db::RESTORE_PRIOR );
478 
479  $this->assertFalse( (bool)$db->trxLevel(), "Transaction cleared." );
480  }
481 
488  public function testGetScopedLock() {
489  $db = $this->getMockDB( [ 'isOpen', 'getDBname' ] );
490  $db->method( 'isOpen' )->willReturn( true );
491  $db->method( 'getDBname' )->willReturn( 'unittest' );
492 
493  $this->assertEquals( 0, $db->trxLevel() );
494  $this->assertEquals( true, $db->lockIsFree( 'x', __METHOD__ ) );
495  $this->assertEquals( true, $db->lock( 'x', __METHOD__ ) );
496  $this->assertEquals( false, $db->lockIsFree( 'x', __METHOD__ ) );
497  $this->assertEquals( true, $db->unlock( 'x', __METHOD__ ) );
498  $this->assertEquals( true, $db->lockIsFree( 'x', __METHOD__ ) );
499  $this->assertEquals( 0, $db->trxLevel() );
500 
501  $db->setFlag( DBO_TRX );
502  $this->assertEquals( true, $db->lockIsFree( 'x', __METHOD__ ) );
503  $this->assertEquals( true, $db->lock( 'x', __METHOD__ ) );
504  $this->assertEquals( false, $db->lockIsFree( 'x', __METHOD__ ) );
505  $this->assertEquals( true, $db->unlock( 'x', __METHOD__ ) );
506  $this->assertEquals( true, $db->lockIsFree( 'x', __METHOD__ ) );
507  $db->clearFlag( DBO_TRX );
508 
509  // Pending writes with DBO_TRX
510  $this->assertEquals( 0, $db->trxLevel() );
511  $this->assertTrue( $db->lockIsFree( 'meow', __METHOD__ ) );
512  $db->setFlag( DBO_TRX );
513  $db->query( "DELETE FROM test WHERE t = 1" ); // trigger DBO_TRX transaction before lock
514  try {
515  $lock = $db->getScopedLockAndFlush( 'meow', __METHOD__, 1 );
516  $this->fail( "Exception not reached" );
517  } catch ( DBUnexpectedError $e ) {
518  $this->assertEquals( 1, $db->trxLevel(), "Transaction not committed." );
519  $this->assertTrue( $db->lockIsFree( 'meow', __METHOD__ ), 'Lock not acquired' );
520  }
521  $db->rollback( __METHOD__, IDatabase::FLUSHING_ALL_PEERS );
522  // Pending writes without DBO_TRX
523  $db->clearFlag( DBO_TRX );
524  $this->assertEquals( 0, $db->trxLevel() );
525  $this->assertTrue( $db->lockIsFree( 'meow2', __METHOD__ ) );
526  $db->begin( __METHOD__ );
527  $db->query( "DELETE FROM test WHERE t = 1" ); // trigger DBO_TRX transaction before lock
528  try {
529  $lock = $db->getScopedLockAndFlush( 'meow2', __METHOD__, 1 );
530  $this->fail( "Exception not reached" );
531  } catch ( DBUnexpectedError $e ) {
532  $this->assertEquals( 1, $db->trxLevel(), "Transaction not committed." );
533  $this->assertTrue( $db->lockIsFree( 'meow2', __METHOD__ ), 'Lock not acquired' );
534  }
535  $db->rollback( __METHOD__ );
536  // No pending writes, with DBO_TRX
537  $db->setFlag( DBO_TRX );
538  $this->assertEquals( 0, $db->trxLevel() );
539  $this->assertTrue( $db->lockIsFree( 'wuff', __METHOD__ ) );
540  $db->query( "SELECT 1", __METHOD__ );
541  $this->assertEquals( 1, $db->trxLevel() );
542  $lock = $db->getScopedLockAndFlush( 'wuff', __METHOD__, 1 );
543  $this->assertEquals( 0, $db->trxLevel() );
544  $this->assertFalse( $db->lockIsFree( 'wuff', __METHOD__ ), 'Lock already acquired' );
545  $db->rollback( __METHOD__, IDatabase::FLUSHING_ALL_PEERS );
546  // No pending writes, without DBO_TRX
547  $db->clearFlag( DBO_TRX );
548  $this->assertEquals( 0, $db->trxLevel() );
549  $this->assertTrue( $db->lockIsFree( 'wuff2', __METHOD__ ) );
550  $db->begin( __METHOD__ );
551  try {
552  $lock = $db->getScopedLockAndFlush( 'wuff2', __METHOD__, 1 );
553  $this->fail( "Exception not reached" );
554  } catch ( DBUnexpectedError $e ) {
555  $this->assertEquals( 1, $db->trxLevel(), "Transaction not committed." );
556  $this->assertFalse( $db->lockIsFree( 'wuff2', __METHOD__ ), 'Lock not acquired' );
557  }
558  $db->rollback( __METHOD__ );
559  }
560 
566  public function testFlagSetting() {
567  $db = $this->db;
568  $origTrx = $db->getFlag( DBO_TRX );
569  $origSsl = $db->getFlag( DBO_SSL );
570 
571  $origTrx
572  ? $db->clearFlag( DBO_TRX, $db::REMEMBER_PRIOR )
573  : $db->setFlag( DBO_TRX, $db::REMEMBER_PRIOR );
574  $this->assertEquals( !$origTrx, $db->getFlag( DBO_TRX ) );
575 
576  $origSsl
577  ? $db->clearFlag( DBO_SSL, $db::REMEMBER_PRIOR )
578  : $db->setFlag( DBO_SSL, $db::REMEMBER_PRIOR );
579  $this->assertEquals( !$origSsl, $db->getFlag( DBO_SSL ) );
580 
581  $db->restoreFlags( $db::RESTORE_INITIAL );
582  $this->assertEquals( $origTrx, $db->getFlag( DBO_TRX ) );
583  $this->assertEquals( $origSsl, $db->getFlag( DBO_SSL ) );
584 
585  $origTrx
586  ? $db->clearFlag( DBO_TRX, $db::REMEMBER_PRIOR )
587  : $db->setFlag( DBO_TRX, $db::REMEMBER_PRIOR );
588  $origSsl
589  ? $db->clearFlag( DBO_SSL, $db::REMEMBER_PRIOR )
590  : $db->setFlag( DBO_SSL, $db::REMEMBER_PRIOR );
591 
592  $db->restoreFlags();
593  $this->assertEquals( $origSsl, $db->getFlag( DBO_SSL ) );
594  $this->assertEquals( !$origTrx, $db->getFlag( DBO_TRX ) );
595 
596  $db->restoreFlags();
597  $this->assertEquals( $origSsl, $db->getFlag( DBO_SSL ) );
598  $this->assertEquals( $origTrx, $db->getFlag( DBO_TRX ) );
599  }
600 
605  public function testDBOIgnoreSet() {
606  $db = $this->getMockBuilder( DatabaseMysqli::class )
607  ->disableOriginalConstructor()
608  ->setMethods( null )
609  ->getMock();
610 
611  $db->setFlag( Database::DBO_IGNORE );
612  }
613 
618  public function testDBOIgnoreClear() {
619  $db = $this->getMockBuilder( DatabaseMysqli::class )
620  ->disableOriginalConstructor()
621  ->setMethods( null )
622  ->getMock();
623 
624  $db->clearFlag( Database::DBO_IGNORE );
625  }
626 
631  public function testSchemaAndPrefixMutators() {
632  $old = $this->db->tablePrefix();
633  $oldDomain = $this->db->getDomainId();
634  $this->assertInternalType( 'string', $old, 'Prefix is string' );
635  $this->assertSame( $old, $this->db->tablePrefix(), "Prefix unchanged" );
636  $this->assertSame( $old, $this->db->tablePrefix( 'xxx' ) );
637  $this->assertSame( 'xxx', $this->db->tablePrefix(), "Prefix set" );
638  $this->db->tablePrefix( $old );
639  $this->assertNotEquals( 'xxx', $this->db->tablePrefix() );
640  $this->assertSame( $oldDomain, $this->db->getDomainId() );
641 
642  $old = $this->db->dbSchema();
643  $oldDomain = $this->db->getDomainId();
644  $this->assertInternalType( 'string', $old, 'Schema is string' );
645  $this->assertSame( $old, $this->db->dbSchema(), "Schema unchanged" );
646  $this->assertSame( $old, $this->db->dbSchema( 'xxx' ) );
647  $this->assertSame( 'xxx', $this->db->dbSchema(), "Schema set" );
648  $this->db->dbSchema( $old );
649  $this->assertNotEquals( 'xxx', $this->db->dbSchema() );
650  $this->assertSame( $oldDomain, $this->db->getDomainId() );
651  }
652 
656  public function testSelectDomain() {
657  $oldDomain = $this->db->getDomainId();
658  $oldDatabase = $this->db->getDBname();
659  $oldSchema = $this->db->dbSchema();
660  $oldPrefix = $this->db->tablePrefix();
661 
662  $this->db->selectDomain( 'testselectdb-xxx' );
663  $this->assertSame( 'testselectdb', $this->db->getDBname() );
664  $this->assertSame( '', $this->db->dbSchema() );
665  $this->assertSame( 'xxx', $this->db->tablePrefix() );
666 
667  $this->db->selectDomain( $oldDomain );
668  $this->assertSame( $oldDatabase, $this->db->getDBname() );
669  $this->assertSame( $oldSchema, $this->db->dbSchema() );
670  $this->assertSame( $oldPrefix, $this->db->tablePrefix() );
671  $this->assertSame( $oldDomain, $this->db->getDomainId() );
672 
673  $this->db->selectDomain( 'testselectdb-schema-xxx' );
674  $this->assertSame( 'testselectdb', $this->db->getDBname() );
675  $this->assertSame( 'schema', $this->db->dbSchema() );
676  $this->assertSame( 'xxx', $this->db->tablePrefix() );
677 
678  $this->db->selectDomain( $oldDomain );
679  $this->assertSame( $oldDatabase, $this->db->getDBname() );
680  $this->assertSame( $oldSchema, $this->db->dbSchema() );
681  $this->assertSame( $oldPrefix, $this->db->tablePrefix() );
682  $this->assertSame( $oldDomain, $this->db->getDomainId() );
683  }
684 
685 }
Wikimedia\Rdbms\Database
Relational database abstraction object.
Definition: Database.php:48
false
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:187
Wikimedia\Rdbms\DatabaseSqlite
Definition: DatabaseSqlite.php:37
DatabaseTest\setUp
setUp()
Definition: DatabaseTest.php:19
DatabaseTest\getMockDB
getMockDB( $methods=[])
Use this mock instead of DatabaseTestHelper for cases where DatabaseTestHelper is too inflexibile due...
Definition: DatabaseTest.php:430
$tables
this hook is for auditing only RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist & $tables
Definition: hooks.txt:1018
DBO_SSL
const DBO_SSL
Definition: defines.php:17
Wikimedia\Rdbms\DatabasePostgres
Definition: DatabasePostgres.php:33
DBO_IGNORE
const DBO_IGNORE
Definition: defines.php:11
Wikimedia\Rdbms\DatabaseMysqli
Database abstraction object for PHP extension mysqli.
Definition: DatabaseMysqli.php:37
DatabaseTest\testAddQuotes
testAddQuotes( $input, $expected)
provideAddQuotes Wikimedia\Rdbms\Database::addQuotes
Definition: DatabaseTest.php:60
DBO_TRX
const DBO_TRX
Definition: defines.php:12
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
Wikimedia\Rdbms\IDatabase\commit
commit( $fname=__METHOD__, $flush='')
Commits a transaction previously started using begin().
DatabaseTest\testFactory
testFactory()
provideAddQuotes Wikimedia\Rdbms\Database::factory
Definition: DatabaseTest.php:27
DatabaseTest\testSelectDomain
testSelectDomain()
Wikimedia\Rdbms\Database::selectDomain.
Definition: DatabaseTest.php:656
DatabaseTest\testTransactionPreCommitOrIdle
testTransactionPreCommitOrIdle()
Wikimedia\Rdbms\Database::onTransactionPreCommitOrIdle Wikimedia\Rdbms\Database::runOnTransactionPreC...
Definition: DatabaseTest.php:281
DatabaseTest\testFlagSetting
testFlagSetting()
Wikimedia\Rdbms\Database::getFlag Wikimedia\Rdbms\Database::setFlag Wikimedia\Rdbms\Database::restore...
Definition: DatabaseTest.php:566
Wikimedia\Rdbms\LBFactorySingle
An LBFactory class that always returns a single database object.
Definition: LBFactorySingle.php:32
DatabaseTest\testGetScopedLock
testGetScopedLock()
Wikimedia\Rdbms\Database::getScopedLockAndFlush Wikimedia\Rdbms\Database::lock Wikimedia\Rdbms\Databa...
Definition: DatabaseTest.php:488
DatabaseTest\testDBOIgnoreSet
testDBOIgnoreSet()
UnexpectedValueException Wikimedia\Rdbms\Database::setFlag.
Definition: DatabaseTest.php:605
$input
if(is_array( $mode)) switch( $mode) $input
Definition: postprocess-phan.php:141
DatabaseTest\provideTableNamesWithIndexClauseOrJOIN
provideTableNamesWithIndexClauseOrJOIN()
Definition: DatabaseTest.php:129
DatabaseTest\testTransactionResolution
testTransactionResolution()
Wikimedia\Rdbms\Database::onTransactionResolution Wikimedia\Rdbms\Database::runOnTransactionIdleCallb...
Definition: DatabaseTest.php:363
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
DatabaseTest\testSchemaAndPrefixMutators
testSchemaAndPrefixMutators()
Wikimedia\Rdbms\Database::tablePrefix Wikimedia\Rdbms\Database::dbSchema.
Definition: DatabaseTest.php:631
DatabaseTest\testTransactionIdle_TRX
testTransactionIdle_TRX()
Wikimedia\Rdbms\Database::onTransactionCommitOrIdle Wikimedia\Rdbms\Database::runOnTransactionIdleCal...
Definition: DatabaseTest.php:220
array
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2213
DatabaseTest\testTransactionPreCommitOrIdle_TRX
testTransactionPreCommitOrIdle_TRX()
Wikimedia\Rdbms\Database::onTransactionPreCommitOrIdle Wikimedia\Rdbms\Database::runOnTransactionPreC...
Definition: DatabaseTest.php:314
DatabaseTest\testDBOIgnoreClear
testDBOIgnoreClear()
UnexpectedValueException Wikimedia\Rdbms\Database::clearFlag.
Definition: DatabaseTest.php:618
DatabaseTest\testTransactionListener
testTransactionListener()
Wikimedia\Rdbms\Database::setTransactionListener.
Definition: DatabaseTest.php:392
Wikimedia\Rdbms\IDatabase\rollback
rollback( $fname=__METHOD__, $flush='')
Rollback a transaction previously started using begin().
Wikimedia\Rdbms\IDatabase\getFlag
getFlag( $flag)
Returns a boolean whether the flag $flag is set for this connection.
Wikimedia\Rdbms\DBUnexpectedError
Definition: DBUnexpectedError.php:27
DatabaseTest\testFlushSnapshot
testFlushSnapshot()
Wikimedia\Rdbms\Database::flushSnapshot.
Definition: DatabaseTest.php:466
DatabaseTest\testTransactionIdle
testTransactionIdle()
Wikimedia\Rdbms\Database::onTransactionCommitOrIdle Wikimedia\Rdbms\Database::runOnTransactionIdleCal...
Definition: DatabaseTest.php:179
DatabaseTestHelper
Helper for testing the methods from the Database class.
Definition: DatabaseTestHelper.php:11
DatabaseTest\testTableName
testTableName( $expected, $table, $format, array $alias=null)
provideTableName Wikimedia\Rdbms\Database::tableName
Definition: DatabaseTest.php:119
Wikimedia\Rdbms\IDatabase\onTransactionPreCommitOrIdle
onTransactionPreCommitOrIdle(callable $callback, $fname=__METHOD__)
Run a callback before the current transaction commits or now if there is none.
DatabaseTest
Definition: DatabaseTest.php:15
Wikimedia\Rdbms\DatabaseMssql
Definition: DatabaseMssql.php:37
DatabaseTest\testTableNamesWithIndexClauseOrJOIN
testTableNamesWithIndexClauseOrJOIN( $tables, $join_conds, $expect)
provideTableNamesWithIndexClauseOrJOIN Wikimedia\Rdbms\Database::tableNamesWithIndexClauseOrJOIN
Definition: DatabaseTest.php:169
class
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
DatabaseTest\provideAddQuotes
static provideAddQuotes()
Definition: DatabaseTest.php:46
Wikimedia\Rdbms\IDatabase\onTransactionResolution
onTransactionResolution(callable $callback, $fname=__METHOD__)
Run a callback as soon as the current transaction commits or rolls back.
Wikimedia\Rdbms\DatabaseDomain
Class to handle database/prefix specification for IDatabase domains.
Definition: DatabaseDomain.php:28
Wikimedia\Rdbms\TransactionProfiler
Helper class that detects high-contention DB queries via profiling calls.
Definition: TransactionProfiler.php:38
DatabaseTest\provideTableName
static provideTableName()
Definition: DatabaseTest.php:64
Wikimedia\Rdbms\IDatabase\setFlag
setFlag( $flag, $remember=self::REMEMBER_NOTHING)
Set a flag for this connection.
Wikimedia\Rdbms\IDatabase\begin
begin( $fname=__METHOD__, $mode=self::TRANSACTION_EXPLICIT)
Begin a transaction.
Wikimedia\Rdbms\IDatabase\clearFlag
clearFlag( $flag, $remember=self::REMEMBER_NOTHING)
Clear a flag for this connection.