MediaWiki
REL1_24
|
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 }