4 * Test the abstract database layer
5 * This is a non DBMS depending test.
7 class DatabaseSQLTest
extends MediaWikiTestCase
{
11 protected function setUp() {
13 $this->database
= new DatabaseTestHelper( __CLASS__
);
16 protected function assertLastSql( $sqlText ) {
18 $this->database
->getLastSqls(),
24 * @dataProvider provideSelect
26 function testSelect( $sql, $sqlText ) {
27 $this->database
->select(
30 isset( $sql['conds'] ) ?
$sql['conds'] : array(),
32 isset( $sql['options'] ) ?
$sql['options'] : array(),
33 isset( $sql['join_conds'] ) ?
$sql['join_conds'] : array()
35 $this->assertLastSql( $sqlText );
38 public static function provideSelect() {
43 'fields' => array( 'field', 'alias' => 'field2' ),
44 'conds' => array( 'alias' => 'text' ),
46 "SELECT field,field2 AS alias " .
48 "WHERE alias = 'text'"
53 'fields' => array( 'field', 'alias' => 'field2' ),
54 'conds' => array( 'alias' => 'text' ),
55 'options' => array( 'LIMIT' => 1, 'ORDER BY' => 'field' ),
57 "SELECT field,field2 AS alias " .
59 "WHERE alias = 'text' " .
65 'tables' => array( 'table', 't2' => 'table2' ),
66 'fields' => array( 'tid', 'field', 'alias' => 'field2', 't2.id' ),
67 'conds' => array( 'alias' => 'text' ),
68 'options' => array( 'LIMIT' => 1, 'ORDER BY' => 'field' ),
69 'join_conds' => array( 't2' => array(
70 'LEFT JOIN', 'tid = t2.id'
73 "SELECT tid,field,field2 AS alias,t2.id " .
74 "FROM table LEFT JOIN table2 t2 ON ((tid = t2.id)) " .
75 "WHERE alias = 'text' " .
81 'tables' => array( 'table', 't2' => 'table2' ),
82 'fields' => array( 'tid', 'field', 'alias' => 'field2', 't2.id' ),
83 'conds' => array( 'alias' => 'text' ),
84 'options' => array( 'LIMIT' => 1, 'GROUP BY' => 'field', 'HAVING' => 'COUNT(*) > 1' ),
85 'join_conds' => array( 't2' => array(
86 'LEFT JOIN', 'tid = t2.id'
89 "SELECT tid,field,field2 AS alias,t2.id " .
90 "FROM table LEFT JOIN table2 t2 ON ((tid = t2.id)) " .
91 "WHERE alias = 'text' " .
92 "GROUP BY field HAVING COUNT(*) > 1 " .
97 'tables' => array( 'table', 't2' => 'table2' ),
98 'fields' => array( 'tid', 'field', 'alias' => 'field2', 't2.id' ),
99 'conds' => array( 'alias' => 'text' ),
100 'options' => array( 'LIMIT' => 1, 'GROUP BY' => array( 'field', 'field2' ), 'HAVING' => array( 'COUNT(*) > 1', 'field' => 1 ) ),
101 'join_conds' => array( 't2' => array(
102 'LEFT JOIN', 'tid = t2.id'
105 "SELECT tid,field,field2 AS alias,t2.id " .
106 "FROM table LEFT JOIN table2 t2 ON ((tid = t2.id)) " .
107 "WHERE alias = 'text' " .
108 "GROUP BY field,field2 HAVING (COUNT(*) > 1) AND field = '1' " .
113 'tables' => array( 'table' ),
114 'fields' => array( 'alias' => 'field' ),
115 'conds' => array( 'alias' => array( 1, 2, 3, 4 ) ),
117 "SELECT field AS alias " .
119 "WHERE alias IN ('1','2','3','4')"
125 * @dataProvider provideUpdate
127 function testUpdate( $sql, $sqlText ) {
128 $this->database
->update(
133 isset( $sql['options'] ) ?
$sql['options'] : array()
135 $this->assertLastSql( $sqlText );
138 public static function provideUpdate() {
143 'values' => array( 'field' => 'text', 'field2' => 'text2' ),
144 'conds' => array( 'alias' => 'text' ),
147 "SET field = 'text'" .
148 ",field2 = 'text2' " .
149 "WHERE alias = 'text'"
154 'values' => array( 'field = other', 'field2' => 'text2' ),
155 'conds' => array( 'id' => '1' ),
158 "SET field = other" .
159 ",field2 = 'text2' " .
165 'values' => array( 'field = other', 'field2' => 'text2' ),
169 "SET field = other" .
176 * @dataProvider provideDelete
178 function testDelete( $sql, $sqlText ) {
179 $this->database
->delete(
184 $this->assertLastSql( $sqlText );
187 public static function provideDelete() {
192 'conds' => array( 'alias' => 'text' ),
194 "DELETE FROM table " .
195 "WHERE alias = 'text'"
208 * @dataProvider provideUpsert
210 function testUpsert( $sql, $sqlText ) {
211 $this->database
->upsert(
214 $sql['uniqueIndexes'],
218 $this->assertLastSql( $sqlText );
221 public static function provideUpsert() {
225 'table' => 'upsert_table',
226 'rows' => array( 'field' => 'text', 'field2' => 'text2' ),
227 'uniqueIndexes' => array( 'field' ),
228 'set' => array( 'field' => 'set' ),
231 "UPDATE upsert_table " .
232 "SET field = 'set' " .
233 "WHERE ((field = 'text')); " .
234 "INSERT IGNORE INTO upsert_table " .
236 "VALUES ('text','text2'); " .
243 * @dataProvider provideDeleteJoin
245 function testDeleteJoin( $sql, $sqlText ) {
246 $this->database
->deleteJoin(
254 $this->assertLastSql( $sqlText );
257 public static function provideDeleteJoin() {
261 'delTable' => 'table',
262 'joinTable' => 'table_join',
264 'joinVar' => 'field_join',
265 'conds' => array( 'alias' => 'text' ),
267 "DELETE FROM table " .
269 "SELECT field_join FROM table_join WHERE alias = 'text'" .
274 'delTable' => 'table',
275 'joinTable' => 'table_join',
277 'joinVar' => 'field_join',
280 "DELETE FROM table " .
282 "SELECT field_join FROM table_join " .
289 * @dataProvider provideInsert
291 function testInsert( $sql, $sqlText ) {
292 $this->database
->insert(
296 isset( $sql['options'] ) ?
$sql['options'] : array()
298 $this->assertLastSql( $sqlText );
301 public static function provideInsert() {
306 'rows' => array( 'field' => 'text', 'field2' => 2 ),
308 "INSERT INTO table " .
310 "VALUES ('text','2')"
315 'rows' => array( 'field' => 'text', 'field2' => 2 ),
316 'options' => 'IGNORE',
318 "INSERT IGNORE INTO table " .
320 "VALUES ('text','2')"
326 array( 'field' => 'text', 'field2' => 2 ),
327 array( 'field' => 'multi', 'field2' => 3 ),
329 'options' => 'IGNORE',
331 "INSERT IGNORE INTO table " .
341 * @dataProvider provideInsertSelect
343 function testInsertSelect( $sql, $sqlText ) {
344 $this->database
->insertSelect(
350 isset( $sql['insertOptions'] ) ?
$sql['insertOptions'] : array(),
351 isset( $sql['selectOptions'] ) ?
$sql['selectOptions'] : array()
353 $this->assertLastSql( $sqlText );
356 public static function provideInsertSelect() {
360 'destTable' => 'insert_table',
361 'srcTable' => 'select_table',
362 'varMap' => array( 'field_insert' => 'field_select', 'field' => 'field2' ),
365 "INSERT INTO insert_table " .
366 "(field_insert,field) " .
367 "SELECT field_select,field2 " .
372 'destTable' => 'insert_table',
373 'srcTable' => 'select_table',
374 'varMap' => array( 'field_insert' => 'field_select', 'field' => 'field2' ),
375 'conds' => array( 'field' => 2 ),
377 "INSERT INTO insert_table " .
378 "(field_insert,field) " .
379 "SELECT field_select,field2 " .
380 "FROM select_table " .
385 'destTable' => 'insert_table',
386 'srcTable' => 'select_table',
387 'varMap' => array( 'field_insert' => 'field_select', 'field' => 'field2' ),
388 'conds' => array( 'field' => 2 ),
389 'insertOptions' => 'IGNORE',
390 'selectOptions' => array( 'ORDER BY' => 'field' ),
392 "INSERT IGNORE INTO insert_table " .
393 "(field_insert,field) " .
394 "SELECT field_select,field2 " .
395 "FROM select_table " .
396 "WHERE field = '2' " .
403 * @dataProvider provideReplace
405 function testReplace( $sql, $sqlText ) {
406 $this->database
->replace(
408 $sql['uniqueIndexes'],
412 $this->assertLastSql( $sqlText );
415 public static function provideReplace() {
419 'table' => 'replace_table',
420 'uniqueIndexes' => array( 'field' ),
421 'rows' => array( 'field' => 'text', 'field2' => 'text2' ),
423 "DELETE FROM replace_table " .
424 "WHERE ( field='text' ); " .
425 "INSERT INTO replace_table " .
427 "VALUES ('text','text2')"
431 'table' => 'module_deps',
432 'uniqueIndexes' => array( array( 'md_module', 'md_skin' ) ),
434 'md_module' => 'module',
439 "DELETE FROM module_deps " .
440 "WHERE ( md_module='module' AND md_skin='skin' ); " .
441 "INSERT INTO module_deps " .
442 "(md_module,md_skin,md_deps) " .
443 "VALUES ('module','skin','deps')"
447 'table' => 'module_deps',
448 'uniqueIndexes' => array( array( 'md_module', 'md_skin' ) ),
451 'md_module' => 'module',
455 'md_module' => 'module2',
456 'md_skin' => 'skin2',
457 'md_deps' => 'deps2',
461 "DELETE FROM module_deps " .
462 "WHERE ( md_module='module' AND md_skin='skin' ); " .
463 "INSERT INTO module_deps " .
464 "(md_module,md_skin,md_deps) " .
465 "VALUES ('module','skin','deps'); " .
466 "DELETE FROM module_deps " .
467 "WHERE ( md_module='module2' AND md_skin='skin2' ); " .
468 "INSERT INTO module_deps " .
469 "(md_module,md_skin,md_deps) " .
470 "VALUES ('module2','skin2','deps2')"
474 'table' => 'module_deps',
475 'uniqueIndexes' => array( 'md_module', 'md_skin' ),
478 'md_module' => 'module',
482 'md_module' => 'module2',
483 'md_skin' => 'skin2',
484 'md_deps' => 'deps2',
488 "DELETE FROM module_deps " .
489 "WHERE ( md_module='module' ) OR ( md_skin='skin' ); " .
490 "INSERT INTO module_deps " .
491 "(md_module,md_skin,md_deps) " .
492 "VALUES ('module','skin','deps'); " .
493 "DELETE FROM module_deps " .
494 "WHERE ( md_module='module2' ) OR ( md_skin='skin2' ); " .
495 "INSERT INTO module_deps " .
496 "(md_module,md_skin,md_deps) " .
497 "VALUES ('module2','skin2','deps2')"
501 'table' => 'module_deps',
502 'uniqueIndexes' => array(),
504 'md_module' => 'module',
509 "INSERT INTO module_deps " .
510 "(md_module,md_skin,md_deps) " .
511 "VALUES ('module','skin','deps')"
517 * @dataProvider provideNativeReplace
519 function testNativeReplace( $sql, $sqlText ) {
520 $this->database
->nativeReplace(
525 $this->assertLastSql( $sqlText );
528 public static function provideNativeReplace() {
532 'table' => 'replace_table',
533 'rows' => array( 'field' => 'text', 'field2' => 'text2' ),
535 "REPLACE INTO replace_table " .
537 "VALUES ('text','text2')"
543 * @dataProvider provideConditional
545 function testConditional( $sql, $sqlText ) {
546 $this->assertEquals( trim( $this->database
->conditional(
553 public static function provideConditional() {
557 'conds' => array( 'field' => 'text' ),
561 "(CASE WHEN field = 'text' THEN 1 ELSE NULL END)"
565 'conds' => array( 'field' => 'text', 'field2' => 'anothertext' ),
569 "(CASE WHEN field = 'text' AND field2 = 'anothertext' THEN 1 ELSE NULL END)"
573 'conds' => 'field=1',
577 "(CASE WHEN field=1 THEN 1 ELSE NULL END)"
583 * @dataProvider provideBuildConcat
585 function testBuildConcat( $stringList, $sqlText ) {
586 $this->assertEquals( trim( $this->database
->buildConcat(
591 public static function provideBuildConcat() {
594 array( 'field', 'field2' ),
595 "CONCAT(field,field2)"
598 array( "'test'", 'field2' ),
599 "CONCAT('test',field2)"
605 * @dataProvider provideBuildLike
607 function testBuildLike( $array, $sqlText ) {
608 $this->assertEquals( trim( $this->database
->buildLike(
613 public static function provideBuildLike() {
620 array( 'text', new LikeMatch( '%' ) ),
624 array( 'text', new LikeMatch( '%' ), 'text2' ),
628 array( 'text', new LikeMatch( '_' ) ),
635 * @dataProvider provideUnionQueries
637 function testUnionQueries( $sql, $sqlText ) {
638 $this->assertEquals( trim( $this->database
->unionQueries(
644 public static function provideUnionQueries() {
648 'sqls' => array( 'RAW SQL', 'RAW2SQL' ),
651 "(RAW SQL) UNION ALL (RAW2SQL)"
655 'sqls' => array( 'RAW SQL', 'RAW2SQL' ),
658 "(RAW SQL) UNION (RAW2SQL)"
662 'sqls' => array( 'RAW SQL', 'RAW2SQL', 'RAW3SQL' ),
665 "(RAW SQL) UNION (RAW2SQL) UNION (RAW3SQL)"
670 function testTransactionCommit() {
671 $this->database
->begin( __METHOD__
);
672 $this->database
->commit( __METHOD__
);
673 $this->assertLastSql( 'BEGIN; COMMIT' );
676 function testTransactionRollback() {
677 $this->database
->begin( __METHOD__
);
678 $this->database
->rollback( __METHOD__
);
679 $this->assertLastSql( 'BEGIN; ROLLBACK' );
682 function testDropTable() {
683 $this->database
->setExistingTables( array( 'table' ) );
684 $this->database
->dropTable( 'table', __METHOD__
);
685 $this->assertLastSql( 'DROP TABLE table' );
688 function testDropNonExistingTable() {
690 $this->database
->dropTable( 'non_existing', __METHOD__
)