MediaWiki  1.33.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 {
17  private $db;
18 
19  use MediaWikiCoversValidator;
20 
21  protected function setUp() {
22  $this->db = new DatabaseTestHelper( __CLASS__ . '::' . $this->getName() );
23  }
24 
29  public function testFactory() {
30  $m = Database::NEW_UNCONNECTED; // no-connect mode
31  $p = [ 'host' => 'localhost', 'user' => 'me', 'password' => 'myself', 'dbname' => 'i' ];
32 
33  $this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'mysqli', $p, $m ) );
34  $this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'MySqli', $p, $m ) );
35  $this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'MySQLi', $p, $m ) );
36  $this->assertInstanceOf( DatabasePostgres::class, Database::factory( 'postgres', $p, $m ) );
37  $this->assertInstanceOf( DatabasePostgres::class, Database::factory( 'Postgres', $p, $m ) );
38 
39  $x = $p + [ 'port' => 10000, 'UseWindowsAuth' => false ];
40  $this->assertInstanceOf( DatabaseMssql::class, Database::factory( 'mssql', $x, $m ) );
41 
42  $x = $p + [ 'dbFilePath' => 'some/file.sqlite' ];
43  $this->assertInstanceOf( DatabaseSqlite::class, Database::factory( 'sqlite', $x, $m ) );
44  $x = $p + [ 'dbDirectory' => 'some/file' ];
45  $this->assertInstanceOf( DatabaseSqlite::class, Database::factory( 'sqlite', $x, $m ) );
46  }
47 
48  public static function provideAddQuotes() {
49  return [
50  [ null, 'NULL' ],
51  [ 1234, "'1234'" ],
52  [ 1234.5678, "'1234.5678'" ],
53  [ 'string', "'string'" ],
54  [ 'string\'s cause trouble', "'string\'s cause trouble'" ],
55  ];
56  }
57 
62  public function testAddQuotes( $input, $expected ) {
63  $this->assertEquals( $expected, $this->db->addQuotes( $input ) );
64  }
65 
66  public static function provideTableName() {
67  // Formatting is mostly ignored since addIdentifierQuotes is abstract.
68  // For testing of addIdentifierQuotes, see actual Database subclas tests.
69  return [
70  'local' => [
71  'tablename',
72  'tablename',
73  'quoted',
74  ],
75  'local-raw' => [
76  'tablename',
77  'tablename',
78  'raw',
79  ],
80  'shared' => [
81  'sharedb.tablename',
82  'tablename',
83  'quoted',
84  [ 'dbname' => 'sharedb', 'schema' => null, 'prefix' => '' ],
85  ],
86  'shared-raw' => [
87  'sharedb.tablename',
88  'tablename',
89  'raw',
90  [ 'dbname' => 'sharedb', 'schema' => null, 'prefix' => '' ],
91  ],
92  'shared-prefix' => [
93  'sharedb.sh_tablename',
94  'tablename',
95  'quoted',
96  [ 'dbname' => 'sharedb', 'schema' => null, 'prefix' => 'sh_' ],
97  ],
98  'shared-prefix-raw' => [
99  'sharedb.sh_tablename',
100  'tablename',
101  'raw',
102  [ 'dbname' => 'sharedb', 'schema' => null, 'prefix' => 'sh_' ],
103  ],
104  'foreign' => [
105  'databasename.tablename',
106  'databasename.tablename',
107  'quoted',
108  ],
109  'foreign-raw' => [
110  'databasename.tablename',
111  'databasename.tablename',
112  'raw',
113  ],
114  ];
115  }
116 
121  public function testTableName( $expected, $table, $format, array $alias = null ) {
122  if ( $alias ) {
123  $this->db->setTableAliases( [ $table => $alias ] );
124  }
125  $this->assertEquals(
126  $expected,
127  $this->db->tableName( $table, $format ?: 'quoted' )
128  );
129  }
130 
132  return [
133  'one-element array' => [
134  [ 'table' ], [], 'table '
135  ],
136  'comma join' => [
137  [ 'table1', 'table2' ], [], 'table1,table2 '
138  ],
139  'real join' => [
140  [ 'table1', 'table2' ],
141  [ 'table2' => [ 'LEFT JOIN', 't1_id = t2_id' ] ],
142  'table1 LEFT JOIN table2 ON ((t1_id = t2_id))'
143  ],
144  'real join with multiple conditionals' => [
145  [ 'table1', 'table2' ],
146  [ 'table2' => [ 'LEFT JOIN', [ 't1_id = t2_id', 't2_x = \'X\'' ] ] ],
147  'table1 LEFT JOIN table2 ON ((t1_id = t2_id) AND (t2_x = \'X\'))'
148  ],
149  'join with parenthesized group' => [
150  [ 'table1', 'n' => [ 'table2', 'table3' ] ],
151  [
152  'table3' => [ 'JOIN', 't2_id = t3_id' ],
153  'n' => [ 'LEFT JOIN', 't1_id = t2_id' ],
154  ],
155  'table1 LEFT JOIN (table2 JOIN table3 ON ((t2_id = t3_id))) ON ((t1_id = t2_id))'
156  ],
157  'join with degenerate parenthesized group' => [
158  [ 'table1', 'n' => [ 't2' => 'table2' ] ],
159  [
160  'n' => [ 'LEFT JOIN', 't1_id = t2_id' ],
161  ],
162  'table1 LEFT JOIN table2 t2 ON ((t1_id = t2_id))'
163  ],
164  ];
165  }
166 
171  public function testTableNamesWithIndexClauseOrJOIN( $tables, $join_conds, $expect ) {
172  $clause = TestingAccessWrapper::newFromObject( $this->db )
173  ->tableNamesWithIndexClauseOrJOIN( $tables, [], [], $join_conds );
174  $this->assertSame( $expect, $clause );
175  }
176 
181  public function testTransactionIdle() {
182  $db = $this->db;
183 
184  $db->clearFlag( DBO_TRX );
185  $called = false;
186  $flagSet = null;
187  $callback = function ( $trigger, IDatabase $db ) use ( &$flagSet, &$called ) {
188  $called = true;
189  $flagSet = $db->getFlag( DBO_TRX );
190  };
191 
192  $db->onTransactionCommitOrIdle( $callback, __METHOD__ );
193  $this->assertTrue( $called, 'Callback reached' );
194  $this->assertFalse( $flagSet, 'DBO_TRX off in callback' );
195  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX still default' );
196 
197  $flagSet = null;
198  $called = false;
199  $db->startAtomic( __METHOD__ );
200  $db->onTransactionCommitOrIdle( $callback, __METHOD__ );
201  $this->assertFalse( $called, 'Callback not reached during TRX' );
202  $db->endAtomic( __METHOD__ );
203 
204  $this->assertTrue( $called, 'Callback reached after COMMIT' );
205  $this->assertFalse( $flagSet, 'DBO_TRX off in callback' );
206  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX restored to default' );
207 
208  $db->clearFlag( DBO_TRX );
210  function ( $trigger, IDatabase $db ) {
211  $db->setFlag( DBO_TRX );
212  },
213  __METHOD__
214  );
215  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX restored to default' );
216  }
217 
222  public function testTransactionIdle_TRX() {
223  $db = $this->getMockDB( [ 'isOpen', 'ping', 'getDBname' ] );
224  $db->method( 'isOpen' )->willReturn( true );
225  $db->method( 'ping' )->willReturn( true );
226  $db->method( 'getDBname' )->willReturn( '' );
227  $db->setFlag( DBO_TRX );
228 
229  $lbFactory = LBFactorySingle::newFromConnection( $db );
230  // Ask for the connection so that LB sets internal state
231  // about this connection being the master connection
232  $lb = $lbFactory->getMainLB();
233  $conn = $lb->openConnection( $lb->getWriterIndex() );
234  $this->assertSame( $db, $conn, 'Same DB instance' );
235  $this->assertTrue( $db->getFlag( DBO_TRX ), 'DBO_TRX is set' );
236 
237  $called = false;
238  $flagSet = null;
239  $callback = function () use ( $db, &$flagSet, &$called ) {
240  $called = true;
241  $flagSet = $db->getFlag( DBO_TRX );
242  };
243 
244  $db->onTransactionCommitOrIdle( $callback, __METHOD__ );
245  $this->assertTrue( $called, 'Called when idle if DBO_TRX is set' );
246  $this->assertFalse( $flagSet, 'DBO_TRX off in callback' );
247  $this->assertTrue( $db->getFlag( DBO_TRX ), 'DBO_TRX still default' );
248 
249  $called = false;
250  $lbFactory->beginMasterChanges( __METHOD__ );
251  $db->onTransactionCommitOrIdle( $callback, __METHOD__ );
252  $this->assertFalse( $called, 'Not called when lb-transaction is active' );
253 
254  $lbFactory->commitMasterChanges( __METHOD__ );
255  $this->assertTrue( $called, 'Called when lb-transaction is committed' );
256 
257  $called = false;
258  $lbFactory->beginMasterChanges( __METHOD__ );
259  $db->onTransactionCommitOrIdle( $callback, __METHOD__ );
260  $this->assertFalse( $called, 'Not called when lb-transaction is active' );
261 
262  $lbFactory->rollbackMasterChanges( __METHOD__ );
263  $this->assertFalse( $called, 'Not called when lb-transaction is rolled back' );
264 
265  $lbFactory->commitMasterChanges( __METHOD__ );
266  $this->assertFalse( $called, 'Not called in next round commit' );
267 
268  $db->setFlag( DBO_TRX );
269  try {
270  $db->onTransactionCommitOrIdle( function () {
271  throw new RuntimeException( 'test' );
272  } );
273  $this->fail( "Exception not thrown" );
274  } catch ( RuntimeException $e ) {
275  $this->assertTrue( $db->getFlag( DBO_TRX ) );
276  }
277  }
278 
283  public function testTransactionPreCommitOrIdle() {
284  $db = $this->getMockDB( [ 'isOpen' ] );
285  $db->method( 'isOpen' )->willReturn( true );
286  $db->clearFlag( DBO_TRX );
287 
288  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX is not set' );
289 
290  $called = false;
292  function ( IDatabase $db ) use ( &$called ) {
293  $called = true;
294  },
295  __METHOD__
296  );
297  $this->assertTrue( $called, 'Called when idle' );
298 
299  $db->begin( __METHOD__ );
300  $called = false;
302  function ( IDatabase $db ) use ( &$called ) {
303  $called = true;
304  },
305  __METHOD__
306  );
307  $this->assertFalse( $called, 'Not called when transaction is active' );
308  $db->commit( __METHOD__ );
309  $this->assertTrue( $called, 'Called when transaction is committed' );
310  }
311 
317  $db = $this->getMockDB( [ 'isOpen', 'ping', 'getDBname' ] );
318  $db->method( 'isOpen' )->willReturn( true );
319  $db->method( 'ping' )->willReturn( true );
320  $db->method( 'getDBname' )->willReturn( 'unittest' );
321  $db->setFlag( DBO_TRX );
322 
323  $lbFactory = LBFactorySingle::newFromConnection( $db );
324  // Ask for the connection so that LB sets internal state
325  // about this connection being the master connection
326  $lb = $lbFactory->getMainLB();
327  $conn = $lb->openConnection( $lb->getWriterIndex() );
328  $this->assertSame( $db, $conn, 'Same DB instance' );
329 
330  $this->assertFalse( $lb->hasMasterChanges() );
331  $this->assertTrue( $db->getFlag( DBO_TRX ), 'DBO_TRX is set' );
332  $called = false;
333  $callback = function ( IDatabase $db ) use ( &$called ) {
334  $called = true;
335  };
336  $db->onTransactionPreCommitOrIdle( $callback, __METHOD__ );
337  $this->assertTrue( $called, 'Called when idle if DBO_TRX is set' );
338  $called = false;
339  $lbFactory->commitMasterChanges();
340  $this->assertFalse( $called );
341 
342  $called = false;
343  $lbFactory->beginMasterChanges( __METHOD__ );
344  $db->onTransactionPreCommitOrIdle( $callback, __METHOD__ );
345  $this->assertFalse( $called, 'Not called when lb-transaction is active' );
346  $lbFactory->commitMasterChanges( __METHOD__ );
347  $this->assertTrue( $called, 'Called when lb-transaction is committed' );
348 
349  $called = false;
350  $lbFactory->beginMasterChanges( __METHOD__ );
351  $db->onTransactionPreCommitOrIdle( $callback, __METHOD__ );
352  $this->assertFalse( $called, 'Not called when lb-transaction is active' );
353 
354  $lbFactory->rollbackMasterChanges( __METHOD__ );
355  $this->assertFalse( $called, 'Not called when lb-transaction is rolled back' );
356 
357  $lbFactory->commitMasterChanges( __METHOD__ );
358  $this->assertFalse( $called, 'Not called in next round commit' );
359  }
360 
365  public function testTransactionResolution() {
366  $db = $this->db;
367 
368  $db->clearFlag( DBO_TRX );
369  $db->begin( __METHOD__ );
370  $called = false;
371  $db->onTransactionResolution( function ( $trigger, IDatabase $db ) use ( &$called ) {
372  $called = true;
373  $db->setFlag( DBO_TRX );
374  } );
375  $db->commit( __METHOD__ );
376  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX restored to default' );
377  $this->assertTrue( $called, 'Callback reached' );
378 
379  $db->clearFlag( DBO_TRX );
380  $db->begin( __METHOD__ );
381  $called = false;
382  $db->onTransactionResolution( function ( $trigger, IDatabase $db ) use ( &$called ) {
383  $called = true;
384  $db->setFlag( DBO_TRX );
385  } );
386  $db->rollback( __METHOD__ );
387  $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX restored to default' );
388  $this->assertTrue( $called, 'Callback reached' );
389  }
390 
394  public function testTransactionListener() {
395  $db = $this->db;
396 
397  $db->setTransactionListener( 'ping', function () use ( $db, &$called ) {
398  $called = true;
399  } );
400 
401  $called = false;
402  $db->begin( __METHOD__ );
403  $db->commit( __METHOD__ );
404  $this->assertTrue( $called, 'Callback reached' );
405 
406  $called = false;
407  $db->begin( __METHOD__ );
408  $db->commit( __METHOD__ );
409  $this->assertTrue( $called, 'Callback still reached' );
410 
411  $called = false;
412  $db->begin( __METHOD__ );
413  $db->rollback( __METHOD__ );
414  $this->assertTrue( $called, 'Callback reached' );
415 
416  $db->setTransactionListener( 'ping', null );
417  $called = false;
418  $db->begin( __METHOD__ );
419  $db->commit( __METHOD__ );
420  $this->assertFalse( $called, 'Callback not reached' );
421  }
422 
432  private function getMockDB( $methods = [] ) {
433  static $abstractMethods = [
434  'fetchAffectedRowCount',
435  'closeConnection',
436  'dataSeek',
437  'doQuery',
438  'fetchObject', 'fetchRow',
439  'fieldInfo', 'fieldName',
440  'getSoftwareLink', 'getServerVersion',
441  'getType',
442  'indexInfo',
443  'insertId',
444  'lastError', 'lastErrno',
445  'numFields', 'numRows',
446  'open',
447  'strencode',
448  'tableExists'
449  ];
450  $db = $this->getMockBuilder( Database::class )
451  ->disableOriginalConstructor()
452  ->setMethods( array_values( array_unique( array_merge(
453  $abstractMethods,
454  $methods
455  ) ) ) )
456  ->getMock();
457  $wdb = TestingAccessWrapper::newFromObject( $db );
458  $wdb->trxProfiler = new TransactionProfiler();
459  $wdb->connLogger = new \Psr\Log\NullLogger();
460  $wdb->queryLogger = new \Psr\Log\NullLogger();
461  $wdb->currentDomain = DatabaseDomain::newUnspecified();
462  return $db;
463  }
464 
468  public function testFlushSnapshot() {
469  $db = $this->getMockDB( [ 'isOpen' ] );
470  $db->method( 'isOpen' )->willReturn( true );
471 
472  $db->flushSnapshot( __METHOD__ ); // ok
473  $db->flushSnapshot( __METHOD__ ); // ok
474 
475  $db->setFlag( DBO_TRX, $db::REMEMBER_PRIOR );
476  $db->query( 'SELECT 1', __METHOD__ );
477  $this->assertTrue( (bool)$db->trxLevel(), "Transaction started." );
478  $db->flushSnapshot( __METHOD__ ); // ok
479  $db->restoreFlags( $db::RESTORE_PRIOR );
480 
481  $this->assertFalse( (bool)$db->trxLevel(), "Transaction cleared." );
482  }
483 
490  public function testGetScopedLock() {
491  $db = $this->getMockDB( [ 'isOpen', 'getDBname' ] );
492  $db->method( 'isOpen' )->willReturn( true );
493  $db->method( 'getDBname' )->willReturn( 'unittest' );
494 
495  $this->assertEquals( 0, $db->trxLevel() );
496  $this->assertEquals( true, $db->lockIsFree( 'x', __METHOD__ ) );
497  $this->assertEquals( true, $db->lock( 'x', __METHOD__ ) );
498  $this->assertEquals( false, $db->lockIsFree( 'x', __METHOD__ ) );
499  $this->assertEquals( true, $db->unlock( 'x', __METHOD__ ) );
500  $this->assertEquals( true, $db->lockIsFree( 'x', __METHOD__ ) );
501  $this->assertEquals( 0, $db->trxLevel() );
502 
503  $db->setFlag( DBO_TRX );
504  $this->assertEquals( true, $db->lockIsFree( 'x', __METHOD__ ) );
505  $this->assertEquals( true, $db->lock( 'x', __METHOD__ ) );
506  $this->assertEquals( false, $db->lockIsFree( 'x', __METHOD__ ) );
507  $this->assertEquals( true, $db->unlock( 'x', __METHOD__ ) );
508  $this->assertEquals( true, $db->lockIsFree( 'x', __METHOD__ ) );
509  $db->clearFlag( DBO_TRX );
510 
511  // Pending writes with DBO_TRX
512  $this->assertEquals( 0, $db->trxLevel() );
513  $this->assertTrue( $db->lockIsFree( 'meow', __METHOD__ ) );
514  $db->setFlag( DBO_TRX );
515  $db->query( "DELETE FROM test WHERE t = 1" ); // trigger DBO_TRX transaction before lock
516  try {
517  $lock = $db->getScopedLockAndFlush( 'meow', __METHOD__, 1 );
518  $this->fail( "Exception not reached" );
519  } catch ( DBUnexpectedError $e ) {
520  $this->assertEquals( 1, $db->trxLevel(), "Transaction not committed." );
521  $this->assertTrue( $db->lockIsFree( 'meow', __METHOD__ ), 'Lock not acquired' );
522  }
523  $db->rollback( __METHOD__, IDatabase::FLUSHING_ALL_PEERS );
524  // Pending writes without DBO_TRX
525  $db->clearFlag( DBO_TRX );
526  $this->assertEquals( 0, $db->trxLevel() );
527  $this->assertTrue( $db->lockIsFree( 'meow2', __METHOD__ ) );
528  $db->begin( __METHOD__ );
529  $db->query( "DELETE FROM test WHERE t = 1" ); // trigger DBO_TRX transaction before lock
530  try {
531  $lock = $db->getScopedLockAndFlush( 'meow2', __METHOD__, 1 );
532  $this->fail( "Exception not reached" );
533  } catch ( DBUnexpectedError $e ) {
534  $this->assertEquals( 1, $db->trxLevel(), "Transaction not committed." );
535  $this->assertTrue( $db->lockIsFree( 'meow2', __METHOD__ ), 'Lock not acquired' );
536  }
537  $db->rollback( __METHOD__ );
538  // No pending writes, with DBO_TRX
539  $db->setFlag( DBO_TRX );
540  $this->assertEquals( 0, $db->trxLevel() );
541  $this->assertTrue( $db->lockIsFree( 'wuff', __METHOD__ ) );
542  $db->query( "SELECT 1", __METHOD__ );
543  $this->assertEquals( 1, $db->trxLevel() );
544  $lock = $db->getScopedLockAndFlush( 'wuff', __METHOD__, 1 );
545  $this->assertEquals( 0, $db->trxLevel() );
546  $this->assertFalse( $db->lockIsFree( 'wuff', __METHOD__ ), 'Lock already acquired' );
547  $db->rollback( __METHOD__, IDatabase::FLUSHING_ALL_PEERS );
548  // No pending writes, without DBO_TRX
549  $db->clearFlag( DBO_TRX );
550  $this->assertEquals( 0, $db->trxLevel() );
551  $this->assertTrue( $db->lockIsFree( 'wuff2', __METHOD__ ) );
552  $db->begin( __METHOD__ );
553  try {
554  $lock = $db->getScopedLockAndFlush( 'wuff2', __METHOD__, 1 );
555  $this->fail( "Exception not reached" );
556  } catch ( DBUnexpectedError $e ) {
557  $this->assertEquals( 1, $db->trxLevel(), "Transaction not committed." );
558  $this->assertFalse( $db->lockIsFree( 'wuff2', __METHOD__ ), 'Lock not acquired' );
559  }
560  $db->rollback( __METHOD__ );
561  }
562 
568  public function testFlagSetting() {
569  $db = $this->db;
570  $origTrx = $db->getFlag( DBO_TRX );
571  $origSsl = $db->getFlag( DBO_SSL );
572 
573  $origTrx
574  ? $db->clearFlag( DBO_TRX, $db::REMEMBER_PRIOR )
575  : $db->setFlag( DBO_TRX, $db::REMEMBER_PRIOR );
576  $this->assertEquals( !$origTrx, $db->getFlag( DBO_TRX ) );
577 
578  $origSsl
579  ? $db->clearFlag( DBO_SSL, $db::REMEMBER_PRIOR )
580  : $db->setFlag( DBO_SSL, $db::REMEMBER_PRIOR );
581  $this->assertEquals( !$origSsl, $db->getFlag( DBO_SSL ) );
582 
583  $db->restoreFlags( $db::RESTORE_INITIAL );
584  $this->assertEquals( $origTrx, $db->getFlag( DBO_TRX ) );
585  $this->assertEquals( $origSsl, $db->getFlag( DBO_SSL ) );
586 
587  $origTrx
588  ? $db->clearFlag( DBO_TRX, $db::REMEMBER_PRIOR )
589  : $db->setFlag( DBO_TRX, $db::REMEMBER_PRIOR );
590  $origSsl
591  ? $db->clearFlag( DBO_SSL, $db::REMEMBER_PRIOR )
592  : $db->setFlag( DBO_SSL, $db::REMEMBER_PRIOR );
593 
594  $db->restoreFlags();
595  $this->assertEquals( $origSsl, $db->getFlag( DBO_SSL ) );
596  $this->assertEquals( !$origTrx, $db->getFlag( DBO_TRX ) );
597 
598  $db->restoreFlags();
599  $this->assertEquals( $origSsl, $db->getFlag( DBO_SSL ) );
600  $this->assertEquals( $origTrx, $db->getFlag( DBO_TRX ) );
601  }
602 
607  public function testDBOIgnoreSet() {
608  $db = $this->getMockBuilder( DatabaseMysqli::class )
609  ->disableOriginalConstructor()
610  ->setMethods( null )
611  ->getMock();
612 
614  }
615 
620  public function testDBOIgnoreClear() {
621  $db = $this->getMockBuilder( DatabaseMysqli::class )
622  ->disableOriginalConstructor()
623  ->setMethods( null )
624  ->getMock();
625 
627  }
628 
633  public function testSchemaAndPrefixMutators() {
634  $ud = DatabaseDomain::newUnspecified();
635 
636  $this->assertEquals( $ud->getId(), $this->db->getDomainID() );
637 
638  $old = $this->db->tablePrefix();
639  $oldDomain = $this->db->getDomainId();
640  $this->assertInternalType( 'string', $old, 'Prefix is string' );
641  $this->assertSame( $old, $this->db->tablePrefix(), "Prefix unchanged" );
642  $this->assertSame( $old, $this->db->tablePrefix( 'xxx_' ) );
643  $this->assertSame( 'xxx_', $this->db->tablePrefix(), "Prefix set" );
644  $this->db->tablePrefix( $old );
645  $this->assertNotEquals( 'xxx_', $this->db->tablePrefix() );
646  $this->assertSame( $oldDomain, $this->db->getDomainId() );
647 
648  $old = $this->db->dbSchema();
649  $oldDomain = $this->db->getDomainId();
650  $this->assertInternalType( 'string', $old, 'Schema is string' );
651  $this->assertSame( $old, $this->db->dbSchema(), "Schema unchanged" );
652 
653  $this->db->selectDB( 'y' );
654  $this->assertSame( $old, $this->db->dbSchema( 'xxx' ) );
655  $this->assertSame( 'xxx', $this->db->dbSchema(), "Schema set" );
656  $this->db->dbSchema( $old );
657  $this->assertNotEquals( 'xxx', $this->db->dbSchema() );
658  $this->assertSame( "y", $this->db->getDomainId() );
659  }
660 
666  public function testSchemaWithNoDB() {
667  $ud = DatabaseDomain::newUnspecified();
668 
669  $this->assertEquals( $ud->getId(), $this->db->getDomainID() );
670  $this->assertSame( '', $this->db->dbSchema() );
671 
672  $this->db->dbSchema( 'xxx' );
673  }
674 
678  public function testSelectDomain() {
679  $oldDomain = $this->db->getDomainId();
680  $oldDatabase = $this->db->getDBname();
681  $oldSchema = $this->db->dbSchema();
682  $oldPrefix = $this->db->tablePrefix();
683 
684  $this->db->selectDomain( 'testselectdb-xxx_' );
685  $this->assertSame( 'testselectdb', $this->db->getDBname() );
686  $this->assertSame( '', $this->db->dbSchema() );
687  $this->assertSame( 'xxx_', $this->db->tablePrefix() );
688 
689  $this->db->selectDomain( $oldDomain );
690  $this->assertSame( $oldDatabase, $this->db->getDBname() );
691  $this->assertSame( $oldSchema, $this->db->dbSchema() );
692  $this->assertSame( $oldPrefix, $this->db->tablePrefix() );
693  $this->assertSame( $oldDomain, $this->db->getDomainId() );
694 
695  $this->db->selectDomain( 'testselectdb-schema-xxx_' );
696  $this->assertSame( 'testselectdb', $this->db->getDBname() );
697  $this->assertSame( 'schema', $this->db->dbSchema() );
698  $this->assertSame( 'xxx_', $this->db->tablePrefix() );
699 
700  $this->db->selectDomain( $oldDomain );
701  $this->assertSame( $oldDatabase, $this->db->getDBname() );
702  $this->assertSame( $oldSchema, $this->db->dbSchema() );
703  $this->assertSame( $oldPrefix, $this->db->tablePrefix() );
704  $this->assertSame( $oldDomain, $this->db->getDomainId() );
705  }
706 
707 }
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:38
DatabaseTest\setUp
setUp()
Definition: DatabaseTest.php:21
Wikimedia\Rdbms\Database\onTransactionPreCommitOrIdle
onTransactionPreCommitOrIdle(callable $callback, $fname=__METHOD__)
Run a callback before the current transaction commits or now if there is none.
Definition: Database.php:3444
DatabaseTest\getMockDB
getMockDB( $methods=[])
Use this mock instead of DatabaseTestHelper for cases where DatabaseTestHelper is too inflexibile due...
Definition: DatabaseTest.php:432
DatabaseTestHelper\query
query( $sql, $fname='', $flags=0)
Run an SQL query and return the result.
Definition: DatabaseTestHelper.php:136
Wikimedia\Rdbms\Database\endAtomic
endAtomic( $fname=__METHOD__)
Ends an atomic section of SQL statements.
Definition: Database.php:3771
$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:979
DatabaseTest\$db
DatabaseTestHelper $db
Definition: DatabaseTest.php:17
Wikimedia\Rdbms\Database\onTransactionCommitOrIdle
onTransactionCommitOrIdle(callable $callback, $fname=__METHOD__)
Run a callback as soon as there is no transaction pending.
Definition: Database.php:3427
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:62
Wikimedia\Rdbms\Database\getFlag
getFlag( $flag)
Returns a boolean whether the flag $flag is set for this connection.
Definition: Database.php:835
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\Database\clearFlag
clearFlag( $flag, $remember=self::REMEMBER_NOTHING)
Clear a flag for this connection.
Definition: Database.php:811
Wikimedia\Rdbms\Database\begin
begin( $fname=__METHOD__, $mode=self::TRANSACTION_EXPLICIT)
Begin a transaction.
Definition: Database.php:3894
DatabaseTest\testFactory
testFactory()
provideAddQuotes Wikimedia\Rdbms\Database::factory
Definition: DatabaseTest.php:29
DatabaseTest\testSelectDomain
testSelectDomain()
Wikimedia\Rdbms\Database::selectDomain.
Definition: DatabaseTest.php:678
Wikimedia\Rdbms\Database\rollback
rollback( $fname=__METHOD__, $flush='')
Rollback a transaction previously started using begin().
Definition: Database.php:4031
DatabaseTest\testTransactionPreCommitOrIdle
testTransactionPreCommitOrIdle()
Wikimedia\Rdbms\Database::onTransactionPreCommitOrIdle Wikimedia\Rdbms\Database::runOnTransactionPreC...
Definition: DatabaseTest.php:283
DatabaseTest\testFlagSetting
testFlagSetting()
Wikimedia\Rdbms\Database::getFlag Wikimedia\Rdbms\Database::setFlag Wikimedia\Rdbms\Database::restore...
Definition: DatabaseTest.php:568
Wikimedia\Rdbms\Database\startAtomic
startAtomic( $fname=__METHOD__, $cancelable=self::ATOMIC_NOT_CANCELABLE)
Begin an atomic section of SQL statements.
Definition: Database.php:3741
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:490
Wikimedia\Rdbms\Database\lock
lock( $lockName, $method, $timeout=5)
Acquire a named lock.
Definition: Database.php:4555
Wikimedia\Rdbms\Database\trxLevel
trxLevel()
Gets the current transaction level.
Definition: Database.php:588
DatabaseTest\testDBOIgnoreSet
testDBOIgnoreSet()
UnexpectedValueException Wikimedia\Rdbms\Database::setFlag.
Definition: DatabaseTest.php:607
$input
if(is_array( $mode)) switch( $mode) $input
Definition: postprocess-phan.php:141
Wikimedia\Rdbms\Database\setFlag
setFlag( $flag, $remember=self::REMEMBER_NOTHING)
Set a flag for this connection.
Definition: Database.php:800
Wikimedia\Rdbms\Database\setTransactionListener
setTransactionListener( $name, callable $callback=null)
Run a callback after each time any transaction commits or rolls back.
Definition: Database.php:3532
DatabaseTest\provideTableNamesWithIndexClauseOrJOIN
provideTableNamesWithIndexClauseOrJOIN()
Definition: DatabaseTest.php:131
DatabaseTest\testTransactionResolution
testTransactionResolution()
Wikimedia\Rdbms\Database::onTransactionResolution Wikimedia\Rdbms\Database::runOnTransactionIdleCallb...
Definition: DatabaseTest.php:365
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:633
Wikimedia\Rdbms\Database\commit
commit( $fname=__METHOD__, $flush=self::FLUSHING_ONE)
Commits a transaction previously started using begin().
Definition: Database.php:3957
DatabaseTest\testTransactionIdle_TRX
testTransactionIdle_TRX()
Wikimedia\Rdbms\Database::onTransactionCommitOrIdle Wikimedia\Rdbms\Database::runOnTransactionIdleCal...
Definition: DatabaseTest.php:222
Wikimedia\Rdbms\Database\restoreFlags
restoreFlags( $state=self::RESTORE_PRIOR)
Restore the flags to their prior state before the last setFlag/clearFlag call.
Definition: Database.php:822
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))
Wikimedia\Rdbms\Database\getScopedLockAndFlush
getScopedLockAndFlush( $lockKey, $fname, $timeout)
Acquire a named lock, flush any transaction, and return an RAII style unlocker object.
Definition: Database.php:4567
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2162
DatabaseTest\testTransactionPreCommitOrIdle_TRX
testTransactionPreCommitOrIdle_TRX()
Wikimedia\Rdbms\Database::onTransactionPreCommitOrIdle Wikimedia\Rdbms\Database::runOnTransactionPreC...
Definition: DatabaseTest.php:316
DatabaseTest\testDBOIgnoreClear
testDBOIgnoreClear()
UnexpectedValueException Wikimedia\Rdbms\Database::clearFlag.
Definition: DatabaseTest.php:620
DatabaseTest\testTransactionListener
testTransactionListener()
Wikimedia\Rdbms\Database::setTransactionListener.
Definition: DatabaseTest.php:394
Wikimedia\Rdbms\DBUnexpectedError
Definition: DBUnexpectedError.php:27
DatabaseTest\testFlushSnapshot
testFlushSnapshot()
Wikimedia\Rdbms\Database::flushSnapshot.
Definition: DatabaseTest.php:468
Wikimedia\Rdbms\Database\unlock
unlock( $lockName, $method)
Release a lock.
Definition: Database.php:4561
DatabaseTest\testTransactionIdle
testTransactionIdle()
Wikimedia\Rdbms\Database::onTransactionCommitOrIdle Wikimedia\Rdbms\Database::runOnTransactionIdleCal...
Definition: DatabaseTest.php:181
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:121
Wikimedia\Rdbms\Database\flushSnapshot
flushSnapshot( $fname=__METHOD__)
Commit any transaction but error out if writes or callbacks are pending.
Definition: Database.php:4101
DatabaseTest
Definition: DatabaseTest.php:15
Wikimedia\Rdbms\Database\lockIsFree
lockIsFree( $lockName, $method)
Check to see if a named lock is not locked by any thread (non-blocking)
Definition: Database.php:4548
Wikimedia\Rdbms\DatabaseMssql
Definition: DatabaseMssql.php:37
DatabaseTest\testSchemaWithNoDB
testSchemaWithNoDB()
Wikimedia\Rdbms\Database::tablePrefix Wikimedia\Rdbms\Database::dbSchema DBUnexpectedError.
Definition: DatabaseTest.php:666
Wikimedia\Rdbms\Database\onTransactionResolution
onTransactionResolution(callable $callback, $fname=__METHOD__)
Run a callback as soon as the current transaction commits or rolls back.
Definition: Database.php:3420
DatabaseTest\testTableNamesWithIndexClauseOrJOIN
testTableNamesWithIndexClauseOrJOIN( $tables, $join_conds, $expect)
provideTableNamesWithIndexClauseOrJOIN Wikimedia\Rdbms\Database::tableNamesWithIndexClauseOrJOIN
Definition: DatabaseTest.php:171
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:48
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:66