MediaWiki  REL1_24
DatabaseSQLTest.php
Go to the documentation of this file.
00001 <?php
00002 
00007 class DatabaseSQLTest extends MediaWikiTestCase {
00008 
00012     private $database;
00013 
00014     protected function setUp() {
00015         parent::setUp();
00016         $this->database = new DatabaseTestHelper( __CLASS__ );
00017     }
00018 
00019     protected function assertLastSql( $sqlText ) {
00020         $this->assertEquals(
00021             $this->database->getLastSqls(),
00022             $sqlText
00023         );
00024     }
00025 
00030     public function testSelect( $sql, $sqlText ) {
00031         $this->database->select(
00032             $sql['tables'],
00033             $sql['fields'],
00034             isset( $sql['conds'] ) ? $sql['conds'] : array(),
00035             __METHOD__,
00036             isset( $sql['options'] ) ? $sql['options'] : array(),
00037             isset( $sql['join_conds'] ) ? $sql['join_conds'] : array()
00038         );
00039         $this->assertLastSql( $sqlText );
00040     }
00041 
00042     public static function provideSelect() {
00043         return array(
00044             array(
00045                 array(
00046                     'tables' => 'table',
00047                     'fields' => array( 'field', 'alias' => 'field2' ),
00048                     'conds' => array( 'alias' => 'text' ),
00049                 ),
00050                 "SELECT field,field2 AS alias " .
00051                     "FROM table " .
00052                     "WHERE alias = 'text'"
00053             ),
00054             array(
00055                 array(
00056                     'tables' => 'table',
00057                     'fields' => array( 'field', 'alias' => 'field2' ),
00058                     'conds' => array( 'alias' => 'text' ),
00059                     'options' => array( 'LIMIT' => 1, 'ORDER BY' => 'field' ),
00060                 ),
00061                 "SELECT field,field2 AS alias " .
00062                     "FROM table " .
00063                     "WHERE alias = 'text' " .
00064                     "ORDER BY field " .
00065                     "LIMIT 1"
00066             ),
00067             array(
00068                 array(
00069                     'tables' => array( 'table', 't2' => 'table2' ),
00070                     'fields' => array( 'tid', 'field', 'alias' => 'field2', 't2.id' ),
00071                     'conds' => array( 'alias' => 'text' ),
00072                     'options' => array( 'LIMIT' => 1, 'ORDER BY' => 'field' ),
00073                     'join_conds' => array( 't2' => array(
00074                         'LEFT JOIN', 'tid = t2.id'
00075                     ) ),
00076                 ),
00077                 "SELECT tid,field,field2 AS alias,t2.id " .
00078                     "FROM table LEFT JOIN table2 t2 ON ((tid = t2.id)) " .
00079                     "WHERE alias = 'text' " .
00080                     "ORDER BY field " .
00081                     "LIMIT 1"
00082             ),
00083             array(
00084                 array(
00085                     'tables' => array( 'table', 't2' => 'table2' ),
00086                     'fields' => array( 'tid', 'field', 'alias' => 'field2', 't2.id' ),
00087                     'conds' => array( 'alias' => 'text' ),
00088                     'options' => array( 'LIMIT' => 1, 'GROUP BY' => 'field', 'HAVING' => 'COUNT(*) > 1' ),
00089                     'join_conds' => array( 't2' => array(
00090                         'LEFT JOIN', 'tid = t2.id'
00091                     ) ),
00092                 ),
00093                 "SELECT tid,field,field2 AS alias,t2.id " .
00094                     "FROM table LEFT JOIN table2 t2 ON ((tid = t2.id)) " .
00095                     "WHERE alias = 'text' " .
00096                     "GROUP BY field HAVING COUNT(*) > 1 " .
00097                     "LIMIT 1"
00098             ),
00099             array(
00100                 array(
00101                     'tables' => array( 'table', 't2' => 'table2' ),
00102                     'fields' => array( 'tid', 'field', 'alias' => 'field2', 't2.id' ),
00103                     'conds' => array( 'alias' => 'text' ),
00104                     'options' => array(
00105                         'LIMIT' => 1,
00106                         'GROUP BY' => array( 'field', 'field2' ),
00107                         'HAVING' => array( 'COUNT(*) > 1', 'field' => 1 )
00108                     ),
00109                     'join_conds' => array( 't2' => array(
00110                         'LEFT JOIN', 'tid = t2.id'
00111                     ) ),
00112                 ),
00113                 "SELECT tid,field,field2 AS alias,t2.id " .
00114                     "FROM table LEFT JOIN table2 t2 ON ((tid = t2.id)) " .
00115                     "WHERE alias = 'text' " .
00116                     "GROUP BY field,field2 HAVING (COUNT(*) > 1) AND field = '1' " .
00117                     "LIMIT 1"
00118             ),
00119             array(
00120                 array(
00121                     'tables' => array( 'table' ),
00122                     'fields' => array( 'alias' => 'field' ),
00123                     'conds' => array( 'alias' => array( 1, 2, 3, 4 ) ),
00124                 ),
00125                 "SELECT field AS alias " .
00126                     "FROM table " .
00127                     "WHERE alias IN ('1','2','3','4')"
00128             ),
00129         );
00130     }
00131 
00136     public function testUpdate( $sql, $sqlText ) {
00137         $this->database->update(
00138             $sql['table'],
00139             $sql['values'],
00140             $sql['conds'],
00141             __METHOD__,
00142             isset( $sql['options'] ) ? $sql['options'] : array()
00143         );
00144         $this->assertLastSql( $sqlText );
00145     }
00146 
00147     public static function provideUpdate() {
00148         return array(
00149             array(
00150                 array(
00151                     'table' => 'table',
00152                     'values' => array( 'field' => 'text', 'field2' => 'text2' ),
00153                     'conds' => array( 'alias' => 'text' ),
00154                 ),
00155                 "UPDATE table " .
00156                     "SET field = 'text'" .
00157                     ",field2 = 'text2' " .
00158                     "WHERE alias = 'text'"
00159             ),
00160             array(
00161                 array(
00162                     'table' => 'table',
00163                     'values' => array( 'field = other', 'field2' => 'text2' ),
00164                     'conds' => array( 'id' => '1' ),
00165                 ),
00166                 "UPDATE table " .
00167                     "SET field = other" .
00168                     ",field2 = 'text2' " .
00169                     "WHERE id = '1'"
00170             ),
00171             array(
00172                 array(
00173                     'table' => 'table',
00174                     'values' => array( 'field = other', 'field2' => 'text2' ),
00175                     'conds' => '*',
00176                 ),
00177                 "UPDATE table " .
00178                     "SET field = other" .
00179                     ",field2 = 'text2'"
00180             ),
00181         );
00182     }
00183 
00188     public function testDelete( $sql, $sqlText ) {
00189         $this->database->delete(
00190             $sql['table'],
00191             $sql['conds'],
00192             __METHOD__
00193         );
00194         $this->assertLastSql( $sqlText );
00195     }
00196 
00197     public static function provideDelete() {
00198         return array(
00199             array(
00200                 array(
00201                     'table' => 'table',
00202                     'conds' => array( 'alias' => 'text' ),
00203                 ),
00204                 "DELETE FROM table " .
00205                     "WHERE alias = 'text'"
00206             ),
00207             array(
00208                 array(
00209                     'table' => 'table',
00210                     'conds' => '*',
00211                 ),
00212                 "DELETE FROM table"
00213             ),
00214         );
00215     }
00216 
00221     public function testUpsert( $sql, $sqlText ) {
00222         $this->database->upsert(
00223             $sql['table'],
00224             $sql['rows'],
00225             $sql['uniqueIndexes'],
00226             $sql['set'],
00227             __METHOD__
00228         );
00229         $this->assertLastSql( $sqlText );
00230     }
00231 
00232     public static function provideUpsert() {
00233         return array(
00234             array(
00235                 array(
00236                     'table' => 'upsert_table',
00237                     'rows' => array( 'field' => 'text', 'field2' => 'text2' ),
00238                     'uniqueIndexes' => array( 'field' ),
00239                     'set' => array( 'field' => 'set' ),
00240                 ),
00241                 "BEGIN; " .
00242                     "UPDATE upsert_table " .
00243                     "SET field = 'set' " .
00244                     "WHERE ((field = 'text')); " .
00245                     "INSERT IGNORE INTO upsert_table " .
00246                     "(field,field2) " .
00247                     "VALUES ('text','text2'); " .
00248                     "COMMIT"
00249             ),
00250         );
00251     }
00252 
00257     public function testDeleteJoin( $sql, $sqlText ) {
00258         $this->database->deleteJoin(
00259             $sql['delTable'],
00260             $sql['joinTable'],
00261             $sql['delVar'],
00262             $sql['joinVar'],
00263             $sql['conds'],
00264             __METHOD__
00265         );
00266         $this->assertLastSql( $sqlText );
00267     }
00268 
00269     public static function provideDeleteJoin() {
00270         return array(
00271             array(
00272                 array(
00273                     'delTable' => 'table',
00274                     'joinTable' => 'table_join',
00275                     'delVar' => 'field',
00276                     'joinVar' => 'field_join',
00277                     'conds' => array( 'alias' => 'text' ),
00278                 ),
00279                 "DELETE FROM table " .
00280                     "WHERE field IN (" .
00281                     "SELECT field_join FROM table_join WHERE alias = 'text'" .
00282                     ")"
00283             ),
00284             array(
00285                 array(
00286                     'delTable' => 'table',
00287                     'joinTable' => 'table_join',
00288                     'delVar' => 'field',
00289                     'joinVar' => 'field_join',
00290                     'conds' => '*',
00291                 ),
00292                 "DELETE FROM table " .
00293                     "WHERE field IN (" .
00294                     "SELECT field_join FROM table_join " .
00295                     ")"
00296             ),
00297         );
00298     }
00299 
00304     public function testInsert( $sql, $sqlText ) {
00305         $this->database->insert(
00306             $sql['table'],
00307             $sql['rows'],
00308             __METHOD__,
00309             isset( $sql['options'] ) ? $sql['options'] : array()
00310         );
00311         $this->assertLastSql( $sqlText );
00312     }
00313 
00314     public static function provideInsert() {
00315         return array(
00316             array(
00317                 array(
00318                     'table' => 'table',
00319                     'rows' => array( 'field' => 'text', 'field2' => 2 ),
00320                 ),
00321                 "INSERT INTO table " .
00322                     "(field,field2) " .
00323                     "VALUES ('text','2')"
00324             ),
00325             array(
00326                 array(
00327                     'table' => 'table',
00328                     'rows' => array( 'field' => 'text', 'field2' => 2 ),
00329                     'options' => 'IGNORE',
00330                 ),
00331                 "INSERT IGNORE INTO table " .
00332                     "(field,field2) " .
00333                     "VALUES ('text','2')"
00334             ),
00335             array(
00336                 array(
00337                     'table' => 'table',
00338                     'rows' => array(
00339                         array( 'field' => 'text', 'field2' => 2 ),
00340                         array( 'field' => 'multi', 'field2' => 3 ),
00341                     ),
00342                     'options' => 'IGNORE',
00343                 ),
00344                 "INSERT IGNORE INTO table " .
00345                     "(field,field2) " .
00346                     "VALUES " .
00347                     "('text','2')," .
00348                     "('multi','3')"
00349             ),
00350         );
00351     }
00352 
00357     public function testInsertSelect( $sql, $sqlText ) {
00358         $this->database->insertSelect(
00359             $sql['destTable'],
00360             $sql['srcTable'],
00361             $sql['varMap'],
00362             $sql['conds'],
00363             __METHOD__,
00364             isset( $sql['insertOptions'] ) ? $sql['insertOptions'] : array(),
00365             isset( $sql['selectOptions'] ) ? $sql['selectOptions'] : array()
00366         );
00367         $this->assertLastSql( $sqlText );
00368     }
00369 
00370     public static function provideInsertSelect() {
00371         return array(
00372             array(
00373                 array(
00374                     'destTable' => 'insert_table',
00375                     'srcTable' => 'select_table',
00376                     'varMap' => array( 'field_insert' => 'field_select', 'field' => 'field2' ),
00377                     'conds' => '*',
00378                 ),
00379                 "INSERT INTO insert_table " .
00380                     "(field_insert,field) " .
00381                     "SELECT field_select,field2 " .
00382                     "FROM select_table"
00383             ),
00384             array(
00385                 array(
00386                     'destTable' => 'insert_table',
00387                     'srcTable' => 'select_table',
00388                     'varMap' => array( 'field_insert' => 'field_select', 'field' => 'field2' ),
00389                     'conds' => array( 'field' => 2 ),
00390                 ),
00391                 "INSERT INTO insert_table " .
00392                     "(field_insert,field) " .
00393                     "SELECT field_select,field2 " .
00394                     "FROM select_table " .
00395                     "WHERE field = '2'"
00396             ),
00397             array(
00398                 array(
00399                     'destTable' => 'insert_table',
00400                     'srcTable' => 'select_table',
00401                     'varMap' => array( 'field_insert' => 'field_select', 'field' => 'field2' ),
00402                     'conds' => array( 'field' => 2 ),
00403                     'insertOptions' => 'IGNORE',
00404                     'selectOptions' => array( 'ORDER BY' => 'field' ),
00405                 ),
00406                 "INSERT IGNORE INTO insert_table " .
00407                     "(field_insert,field) " .
00408                     "SELECT field_select,field2 " .
00409                     "FROM select_table " .
00410                     "WHERE field = '2' " .
00411                     "ORDER BY field"
00412             ),
00413         );
00414     }
00415 
00420     public function testReplace( $sql, $sqlText ) {
00421         $this->database->replace(
00422             $sql['table'],
00423             $sql['uniqueIndexes'],
00424             $sql['rows'],
00425             __METHOD__
00426         );
00427         $this->assertLastSql( $sqlText );
00428     }
00429 
00430     public static function provideReplace() {
00431         return array(
00432             array(
00433                 array(
00434                     'table' => 'replace_table',
00435                     'uniqueIndexes' => array( 'field' ),
00436                     'rows' => array( 'field' => 'text', 'field2' => 'text2' ),
00437                 ),
00438                 "DELETE FROM replace_table " .
00439                     "WHERE ( field='text' ); " .
00440                     "INSERT INTO replace_table " .
00441                     "(field,field2) " .
00442                     "VALUES ('text','text2')"
00443             ),
00444             array(
00445                 array(
00446                     'table' => 'module_deps',
00447                     'uniqueIndexes' => array( array( 'md_module', 'md_skin' ) ),
00448                     'rows' => array(
00449                         'md_module' => 'module',
00450                         'md_skin' => 'skin',
00451                         'md_deps' => 'deps',
00452                     ),
00453                 ),
00454                 "DELETE FROM module_deps " .
00455                     "WHERE ( md_module='module' AND md_skin='skin' ); " .
00456                     "INSERT INTO module_deps " .
00457                     "(md_module,md_skin,md_deps) " .
00458                     "VALUES ('module','skin','deps')"
00459             ),
00460             array(
00461                 array(
00462                     'table' => 'module_deps',
00463                     'uniqueIndexes' => array( array( 'md_module', 'md_skin' ) ),
00464                     'rows' => array(
00465                         array(
00466                             'md_module' => 'module',
00467                             'md_skin' => 'skin',
00468                             'md_deps' => 'deps',
00469                         ), array(
00470                             'md_module' => 'module2',
00471                             'md_skin' => 'skin2',
00472                             'md_deps' => 'deps2',
00473                         ),
00474                     ),
00475                 ),
00476                 "DELETE FROM module_deps " .
00477                     "WHERE ( md_module='module' AND md_skin='skin' ); " .
00478                     "INSERT INTO module_deps " .
00479                     "(md_module,md_skin,md_deps) " .
00480                     "VALUES ('module','skin','deps'); " .
00481                     "DELETE FROM module_deps " .
00482                     "WHERE ( md_module='module2' AND md_skin='skin2' ); " .
00483                     "INSERT INTO module_deps " .
00484                     "(md_module,md_skin,md_deps) " .
00485                     "VALUES ('module2','skin2','deps2')"
00486             ),
00487             array(
00488                 array(
00489                     'table' => 'module_deps',
00490                     'uniqueIndexes' => array( 'md_module', 'md_skin' ),
00491                     'rows' => array(
00492                         array(
00493                             'md_module' => 'module',
00494                             'md_skin' => 'skin',
00495                             'md_deps' => 'deps',
00496                         ), array(
00497                             'md_module' => 'module2',
00498                             'md_skin' => 'skin2',
00499                             'md_deps' => 'deps2',
00500                         ),
00501                     ),
00502                 ),
00503                 "DELETE FROM module_deps " .
00504                     "WHERE ( md_module='module' ) OR ( md_skin='skin' ); " .
00505                     "INSERT INTO module_deps " .
00506                     "(md_module,md_skin,md_deps) " .
00507                     "VALUES ('module','skin','deps'); " .
00508                     "DELETE FROM module_deps " .
00509                     "WHERE ( md_module='module2' ) OR ( md_skin='skin2' ); " .
00510                     "INSERT INTO module_deps " .
00511                     "(md_module,md_skin,md_deps) " .
00512                     "VALUES ('module2','skin2','deps2')"
00513             ),
00514             array(
00515                 array(
00516                     'table' => 'module_deps',
00517                     'uniqueIndexes' => array(),
00518                     'rows' => array(
00519                         'md_module' => 'module',
00520                         'md_skin' => 'skin',
00521                         'md_deps' => 'deps',
00522                     ),
00523                 ),
00524                 "INSERT INTO module_deps " .
00525                     "(md_module,md_skin,md_deps) " .
00526                     "VALUES ('module','skin','deps')"
00527             ),
00528         );
00529     }
00530 
00535     public function testNativeReplace( $sql, $sqlText ) {
00536         $this->database->nativeReplace(
00537             $sql['table'],
00538             $sql['rows'],
00539             __METHOD__
00540         );
00541         $this->assertLastSql( $sqlText );
00542     }
00543 
00544     public static function provideNativeReplace() {
00545         return array(
00546             array(
00547                 array(
00548                     'table' => 'replace_table',
00549                     'rows' => array( 'field' => 'text', 'field2' => 'text2' ),
00550                 ),
00551                 "REPLACE INTO replace_table " .
00552                     "(field,field2) " .
00553                     "VALUES ('text','text2')"
00554             ),
00555         );
00556     }
00557 
00562     public function testConditional( $sql, $sqlText ) {
00563         $this->assertEquals( trim( $this->database->conditional(
00564             $sql['conds'],
00565             $sql['true'],
00566             $sql['false']
00567         ) ), $sqlText );
00568     }
00569 
00570     public static function provideConditional() {
00571         return array(
00572             array(
00573                 array(
00574                     'conds' => array( 'field' => 'text' ),
00575                     'true' => 1,
00576                     'false' => 'NULL',
00577                 ),
00578                 "(CASE WHEN field = 'text' THEN 1 ELSE NULL END)"
00579             ),
00580             array(
00581                 array(
00582                     'conds' => array( 'field' => 'text', 'field2' => 'anothertext' ),
00583                     'true' => 1,
00584                     'false' => 'NULL',
00585                 ),
00586                 "(CASE WHEN field = 'text' AND field2 = 'anothertext' THEN 1 ELSE NULL END)"
00587             ),
00588             array(
00589                 array(
00590                     'conds' => 'field=1',
00591                     'true' => 1,
00592                     'false' => 'NULL',
00593                 ),
00594                 "(CASE WHEN field=1 THEN 1 ELSE NULL END)"
00595             ),
00596         );
00597     }
00598 
00603     public function testBuildConcat( $stringList, $sqlText ) {
00604         $this->assertEquals( trim( $this->database->buildConcat(
00605             $stringList
00606         ) ), $sqlText );
00607     }
00608 
00609     public static function provideBuildConcat() {
00610         return array(
00611             array(
00612                 array( 'field', 'field2' ),
00613                 "CONCAT(field,field2)"
00614             ),
00615             array(
00616                 array( "'test'", 'field2' ),
00617                 "CONCAT('test',field2)"
00618             ),
00619         );
00620     }
00621 
00626     public function testBuildLike( $array, $sqlText ) {
00627         $this->assertEquals( trim( $this->database->buildLike(
00628             $array
00629         ) ), $sqlText );
00630     }
00631 
00632     public static function provideBuildLike() {
00633         return array(
00634             array(
00635                 'text',
00636                 "LIKE 'text'"
00637             ),
00638             array(
00639                 array( 'text', new LikeMatch( '%' ) ),
00640                 "LIKE 'text%'"
00641             ),
00642             array(
00643                 array( 'text', new LikeMatch( '%' ), 'text2' ),
00644                 "LIKE 'text%text2'"
00645             ),
00646             array(
00647                 array( 'text', new LikeMatch( '_' ) ),
00648                 "LIKE 'text_'"
00649             ),
00650         );
00651     }
00652 
00657     public function testUnionQueries( $sql, $sqlText ) {
00658         $this->assertEquals( trim( $this->database->unionQueries(
00659             $sql['sqls'],
00660             $sql['all']
00661         ) ), $sqlText );
00662     }
00663 
00664     public static function provideUnionQueries() {
00665         return array(
00666             array(
00667                 array(
00668                     'sqls' => array( 'RAW SQL', 'RAW2SQL' ),
00669                     'all' => true,
00670                 ),
00671                 "(RAW SQL) UNION ALL (RAW2SQL)"
00672             ),
00673             array(
00674                 array(
00675                     'sqls' => array( 'RAW SQL', 'RAW2SQL' ),
00676                     'all' => false,
00677                 ),
00678                 "(RAW SQL) UNION (RAW2SQL)"
00679             ),
00680             array(
00681                 array(
00682                     'sqls' => array( 'RAW SQL', 'RAW2SQL', 'RAW3SQL' ),
00683                     'all' => false,
00684                 ),
00685                 "(RAW SQL) UNION (RAW2SQL) UNION (RAW3SQL)"
00686             ),
00687         );
00688     }
00689 
00693     public function testTransactionCommit() {
00694         $this->database->begin( __METHOD__ );
00695         $this->database->commit( __METHOD__ );
00696         $this->assertLastSql( 'BEGIN; COMMIT' );
00697     }
00698 
00702     public function testTransactionRollback() {
00703         $this->database->begin( __METHOD__ );
00704         $this->database->rollback( __METHOD__ );
00705         $this->assertLastSql( 'BEGIN; ROLLBACK' );
00706     }
00707 
00711     public function testDropTable() {
00712         $this->database->setExistingTables( array( 'table' ) );
00713         $this->database->dropTable( 'table', __METHOD__ );
00714         $this->assertLastSql( 'DROP TABLE table' );
00715     }
00716 
00720     public function testDropNonExistingTable() {
00721         $this->assertFalse(
00722             $this->database->dropTable( 'non_existing', __METHOD__ )
00723         );
00724     }
00725 }