1 <?php
2
3
4
5
6
7
8
9
10 class FakeRecord { }
11
12
13
14
15
16
17
18 class DatabaseTestCase extends DrupalWebTestCase {
19 protected $profile = 'testing';
20
21 function setUp() {
22 parent::setUp('database_test');
23
24 $schema['test'] = drupal_get_schema('test');
25 $schema['test_people'] = drupal_get_schema('test_people');
26 $schema['test_one_blob'] = drupal_get_schema('test_one_blob');
27 $schema['test_two_blobs'] = drupal_get_schema('test_two_blobs');
28 $schema['test_task'] = drupal_get_schema('test_task');
29
30 $this->installTables($schema);
31
32 $this->addSampleData();
33 }
34
35
36
37
38
39
40
41 function installTables($schema) {
42
43 foreach ($schema as $name => $data) {
44 if (db_table_exists($name)) {
45 db_drop_table($name);
46 }
47 db_create_table($name, $data);
48 }
49
50 foreach ($schema as $name => $data) {
51 $this->assertTrue(db_table_exists($name), t('Table @name created successfully.', array('@name' => $name)));
52 }
53 }
54
55
56
57
58 function ensureSampleDataNull() {
59 $schema['test_null'] = drupal_get_schema('test_null');
60 $this->installTables($schema);
61
62 db_insert('test_null')
63 ->fields(array('name', 'age'))
64 ->values(array(
65 'name' => 'Kermit',
66 'age' => 25,
67 ))
68 ->values(array(
69 'name' => 'Fozzie',
70 'age' => NULL,
71 ))
72 ->values(array(
73 'name' => 'Gonzo',
74 'age' => 27,
75 ))
76 ->execute();
77 }
78
79
80
81
82
83
84
85 function addSampleData() {
86
87 $john = db_insert('test')
88 ->fields(array(
89 'name' => 'John',
90 'age' => 25,
91 'job' => 'Singer',
92 ))
93 ->execute();
94
95 $george = db_insert('test')
96 ->fields(array(
97 'name' => 'George',
98 'age' => 27,
99 'job' => 'Singer',
100 ))
101 ->execute();
102
103 $ringo = db_insert('test')
104 ->fields(array(
105 'name' => 'Ringo',
106 'age' => 28,
107 'job' => 'Drummer',
108 ))
109 ->execute();
110
111 $paul = db_insert('test')
112 ->fields(array(
113 'name' => 'Paul',
114 'age' => 26,
115 'job' => 'Songwriter',
116 ))
117 ->execute();
118
119 db_insert('test_people')
120 ->fields(array(
121 'name' => 'Meredith',
122 'age' => 30,
123 'job' => 'Speaker',
124 ))
125 ->execute();
126
127 db_insert('test_task')
128 ->fields(array('pid', 'task', 'priority'))
129 ->values(array(
130 'pid' => $john,
131 'task' => 'eat',
132 'priority' => 3,
133 ))
134 ->values(array(
135 'pid' => $john,
136 'task' => 'sleep',
137 'priority' => 4,
138 ))
139 ->values(array(
140 'pid' => $john,
141 'task' => 'code',
142 'priority' => 1,
143 ))
144 ->values(array(
145 'pid' => $george,
146 'task' => 'sing',
147 'priority' => 2,
148 ))
149 ->values(array(
150 'pid' => $george,
151 'task' => 'sleep',
152 'priority' => 2,
153 ))
154 ->values(array(
155 'pid' => $paul,
156 'task' => 'found new band',
157 'priority' => 1,
158 ))
159 ->values(array(
160 'pid' => $paul,
161 'task' => 'perform at superbowl',
162 'priority' => 3,
163 ))
164 ->execute();
165 }
166 }
167
168
169
170
171 class DatabaseConnectionTestCase extends DatabaseTestCase {
172
173 public static function getInfo() {
174 return array(
175 'name' => 'Connection tests',
176 'description' => 'Tests of the core database system.',
177 'group' => 'Database',
178 );
179 }
180
181
182
183
184 function testConnectionRouting() {
185
186
187
188 $connection_info = Database::getConnectionInfo('default');
189 Database::addConnectionInfo('default', 'slave', $connection_info['default']);
190
191 $db1 = Database::getConnection('default', 'default');
192 $db2 = Database::getConnection('slave', 'default');
193
194 $this->assertNotNull($db1, t('default connection is a real connection object.'));
195 $this->assertNotNull($db2, t('slave connection is a real connection object.'));
196 $this->assertNotIdentical($db1, $db2, t('Each target refers to a different connection.'));
197
198
199 $db1b = Database::getConnection('default', 'default');
200 $db2b = Database::getConnection('slave', 'default');
201 $this->assertIdentical($db1, $db1b, t('A second call to getConnection() returns the same object.'));
202 $this->assertIdentical($db2, $db2b, t('A second call to getConnection() returns the same object.'));
203
204
205 $unknown_target = $this->randomName();
206 $db3 = Database::getConnection($unknown_target, 'default');
207 $this->assertNotNull($db3, t('Opening an unknown target returns a real connection object.'));
208 $this->assertIdentical($db1, $db3, t('An unknown target opens the default connection.'));
209
210
211 $db3b = Database::getConnection($unknown_target, 'default');
212 $this->assertIdentical($db3, $db3b, t('A second call to getConnection() returns the same object.'));
213 }
214
215
216
217
218 function testConnectionRoutingOverride() {
219
220
221
222 $connection_info = Database::getConnectionInfo('default');
223 Database::addConnectionInfo('default', 'slave', $connection_info['default']);
224
225 Database::ignoreTarget('default', 'slave');
226
227 $db1 = Database::getConnection('default', 'default');
228 $db2 = Database::getConnection('slave', 'default');
229
230 $this->assertIdentical($db1, $db2, t('Both targets refer to the same connection.'));
231 }
232
233
234
235
236 function testConnectionClosing() {
237
238 $db1 = Database::getConnection('default', 'default');
239
240
241 Database::closeConnection('default', 'default');
242 $db2 = Database::getConnection('default', 'default');
243
244
245 $this->assertNotIdentical($db1, $db2, t('Opening the default connection after it is closed returns a new object.'));
246 }
247
248
249
250
251 function testConnectionOptions() {
252 $connection_info = Database::getConnectionInfo('default');
253
254
255 $db = Database::getConnection('default', 'default');
256 $connectionOptions = $db->getConnectionOptions();
257
258
259
260 $this->assertEqual($connection_info['default']['driver'], $connectionOptions['driver'], t('The default connection info driver matches the current connection options driver.'));
261 $this->assertEqual($connection_info['default']['database'], $connectionOptions['database'], t('The default connection info database matches the current connection options database.'));
262
263
264 Database::addConnectionInfo('default', 'slave', $connection_info['default']);
265 $db2 = Database::getConnection('slave', 'default');
266 $connectionOptions2 = $db2->getConnectionOptions();
267
268
269 $connectionOptions = $db->getConnectionOptions();
270 $this->assertIdentical($connectionOptions, $connectionOptions2, t('The default and slave connection options are identical.'));
271
272
273 $test = $connection_info['default'];
274 $test['database'] .= 'test';
275 Database::addConnectionInfo('test', 'default', $test);
276 $connection_info = Database::getConnectionInfo('test');
277
278
279 $connectionOptions = $db->getConnectionOptions();
280 $this->assertNotEqual($connection_info['default']['database'], $connectionOptions['database'], t('The test connection info database does not match the current connection options database.'));
281 }
282 }
283
284
285
286
287
288
289 class DatabaseFetchTestCase extends DatabaseTestCase {
290
291 public static function getInfo() {
292 return array(
293 'name' => 'Fetch tests',
294 'description' => 'Test the Database system\'s various fetch capabilities.',
295 'group' => 'Database',
296 );
297 }
298
299
300
301
302 function testQueryFetchDefault() {
303 $records = array();
304 $result = db_query('SELECT name FROM {test} WHERE age = :age', array(':age' => 25));
305 $this->assertTrue($result instanceof DatabaseStatementInterface, t('Result set is a Drupal statement object.'));
306 foreach ($result as $record) {
307 $records[] = $record;
308 $this->assertTrue(is_object($record), t('Record is an object.'));
309 $this->assertIdentical($record->name, 'John', t('25 year old is John.'));
310 }
311
312 $this->assertIdentical(count($records), 1, t('There is only one record.'));
313 }
314
315
316
317
318 function testQueryFetchObject() {
319 $records = array();
320 $result = db_query('SELECT name FROM {test} WHERE age = :age', array(':age' => 25), array('fetch' => PDO::FETCH_OBJ));
321 foreach ($result as $record) {
322 $records[] = $record;
323 $this->assertTrue(is_object($record), t('Record is an object.'));
324 $this->assertIdentical($record->name, 'John', t('25 year old is John.'));
325 }
326
327 $this->assertIdentical(count($records), 1, t('There is only one record.'));
328 }
329
330
331
332
333 function testQueryFetchArray() {
334 $records = array();
335 $result = db_query('SELECT name FROM {test} WHERE age = :age', array(':age' => 25), array('fetch' => PDO::FETCH_ASSOC));
336 foreach ($result as $record) {
337 $records[] = $record;
338 if ($this->assertTrue(is_array($record), t('Record is an array.'))) {
339 $this->assertIdentical($record['name'], 'John', t('Record can be accessed associatively.'));
340 }
341 }
342
343 $this->assertIdentical(count($records), 1, t('There is only one record.'));
344 }
345
346
347
348
349
350
351 function testQueryFetchClass() {
352 $records = array();
353 $result = db_query('SELECT name FROM {test} WHERE age = :age', array(':age' => 25), array('fetch' => 'FakeRecord'));
354 foreach ($result as $record) {
355 $records[] = $record;
356 if ($this->assertTrue($record instanceof FakeRecord, t('Record is an object of class FakeRecord.'))) {
357 $this->assertIdentical($record->name, 'John', t('25 year old is John.'));
358 }
359 }
360
361 $this->assertIdentical(count($records), 1, t('There is only one record.'));
362 }
363 }
364
365
366
367
368
369
370 class DatabaseFetch2TestCase extends DatabaseTestCase {
371
372 public static function getInfo() {
373 return array(
374 'name' => 'Fetch tests, part 2',
375 'description' => 'Test the Database system\'s various fetch capabilities.',
376 'group' => 'Database',
377 );
378 }
379
380 function setUp() {
381 parent::setUp();
382 }
383
384
385 function testQueryFetchNum() {
386 $records = array();
387 $result = db_query('SELECT name FROM {test} WHERE age = :age', array(':age' => 25), array('fetch' => PDO::FETCH_NUM));
388 foreach ($result as $record) {
389 $records[] = $record;
390 if ($this->assertTrue(is_array($record), t('Record is an array.'))) {
391 $this->assertIdentical($record[0], 'John', t('Record can be accessed numerically.'));
392 }
393 }
394
395 $this->assertIdentical(count($records), 1, 'There is only one record');
396 }
397
398
399
400
401 function testQueryFetchBoth() {
402 $records = array();
403 $result = db_query('SELECT name FROM {test} WHERE age = :age', array(':age' => 25), array('fetch' => PDO::FETCH_BOTH));
404 foreach ($result as $record) {
405 $records[] = $record;
406 if ($this->assertTrue(is_array($record), t('Record is an array.'))) {
407 $this->assertIdentical($record[0], 'John', t('Record can be accessed numerically.'));
408 $this->assertIdentical($record['name'], 'John', t('Record can be accessed associatively.'));
409 }
410 }
411
412 $this->assertIdentical(count($records), 1, t('There is only one record.'));
413 }
414
415
416
417
418 function testQueryFetchCol() {
419 $records = array();
420 $result = db_query('SELECT name FROM {test} WHERE age > :age', array(':age' => 25));
421 $column = $result->fetchCol();
422 $this->assertIdentical(count($column), 3, t('fetchCol() returns the right number of records.'));
423
424 $result = db_query('SELECT name FROM {test} WHERE age > :age', array(':age' => 25));
425 $i = 0;
426 foreach ($result as $record) {
427 $this->assertIdentical($record->name, $column[$i++], t('Column matches direct accesss.'));
428 }
429 }
430 }
431
432
433
434
435 class DatabaseInsertTestCase extends DatabaseTestCase {
436
437 public static function getInfo() {
438 return array(
439 'name' => 'Insert tests',
440 'description' => 'Test the Insert query builder.',
441 'group' => 'Database',
442 );
443 }
444
445
446
447
448 function testSimpleInsert() {
449 $num_records_before = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
450
451 $query = db_insert('test');
452 $query->fields(array(
453 'name' => 'Yoko',
454 'age' => '29',
455 ));
456 $query->execute();
457
458 $num_records_after = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
459 $this->assertIdentical($num_records_before + 1, (int) $num_records_after, t('Record inserts correctly.'));
460 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Yoko'))->fetchField();
461 $this->assertIdentical($saved_age, '29', t('Can retrieve after inserting.'));
462 }
463
464
465
466
467 function testMultiInsert() {
468 $num_records_before = (int) db_query('SELECT COUNT(*) FROM {test}')->fetchField();
469
470 $query = db_insert('test');
471 $query->fields(array(
472 'name' => 'Larry',
473 'age' => '30',
474 ));
475
476
477 $query->values(array(
478 'age' => '31',
479 'name' => 'Curly',
480 ));
481
482
483
484 $query->values(array('Moe', '32'));
485 $query->execute();
486
487 $num_records_after = (int) db_query('SELECT COUNT(*) FROM {test}')->fetchField();
488 $this->assertIdentical($num_records_before + 3, $num_records_after, t('Record inserts correctly.'));
489 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Larry'))->fetchField();
490 $this->assertIdentical($saved_age, '30', t('Can retrieve after inserting.'));
491 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Curly'))->fetchField();
492 $this->assertIdentical($saved_age, '31', t('Can retrieve after inserting.'));
493 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Moe'))->fetchField();
494 $this->assertIdentical($saved_age, '32', t('Can retrieve after inserting.'));
495 }
496
497
498
499
500 function testRepeatedInsert() {
501 $num_records_before = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
502
503 $query = db_insert('test');
504
505 $query->fields(array(
506 'name' => 'Larry',
507 'age' => '30',
508 ));
509 $query->execute();
510
511
512 $query->values(array(
513 'age' => '31',
514 'name' => 'Curly',
515 ));
516 $query->execute();
517
518
519 $query->values(array('Moe', '32'));
520 $query->execute();
521
522 $num_records_after = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
523 $this->assertIdentical((int) $num_records_before + 3, (int) $num_records_after, t('Record inserts correctly.'));
524 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Larry'))->fetchField();
525 $this->assertIdentical($saved_age, '30', t('Can retrieve after inserting.'));
526 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Curly'))->fetchField();
527 $this->assertIdentical($saved_age, '31', t('Can retrieve after inserting.'));
528 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Moe'))->fetchField();
529 $this->assertIdentical($saved_age, '32', t('Can retrieve after inserting.'));
530 }
531
532
533
534
535 function testInsertFieldOnlyDefinintion() {
536
537
538 db_insert('test')
539 ->fields(array('name', 'age'))
540 ->values(array('Larry', '30'))
541 ->values(array('Curly', '31'))
542 ->values(array('Moe', '32'))
543 ->execute();
544 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Larry'))->fetchField();
545 $this->assertIdentical($saved_age, '30', t('Can retrieve after inserting.'));
546 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Curly'))->fetchField();
547 $this->assertIdentical($saved_age, '31', t('Can retrieve after inserting.'));
548 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Moe'))->fetchField();
549 $this->assertIdentical($saved_age, '32', t('Can retrieve after inserting.'));
550 }
551
552
553
554
555 function testInsertLastInsertID() {
556 $id = db_insert('test')
557 ->fields(array(
558 'name' => 'Larry',
559 'age' => '30',
560 ))
561 ->execute();
562
563 $this->assertIdentical($id, '5', t('Auto-increment ID returned successfully.'));
564 }
565
566
567
568
569 function testInsertSelect() {
570 $query = db_select('test_people', 'tp');
571
572
573
574 $query->addExpression('tp.age', 'age');
575 $query
576 ->fields('tp', array('name','job'))
577 ->condition('tp.name', 'Meredith');
578
579
580
581
582
583
584 db_insert('test')
585 ->from($query)
586 ->execute();
587
588 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Meredith'))->fetchField();
589 $this->assertIdentical($saved_age, '30', t('Can retrieve after inserting.'));
590 }
591 }
592
593
594
595
596 class DatabaseInsertLOBTestCase extends DatabaseTestCase {
597
598 public static function getInfo() {
599 return array(
600 'name' => 'Insert tests, LOB fields',
601 'description' => 'Test the Insert query builder with LOB fields.',
602 'group' => 'Database',
603 );
604 }
605
606
607
608
609 function testInsertOneBlob() {
610 $data = "This is\000a test.";
611 $this->assertTrue(strlen($data) === 15, t('Test data contains a NULL.'));
612 $id = db_insert('test_one_blob')
613 ->fields(array('blob1' => $data))
614 ->execute();
615 $r = db_query('SELECT * FROM {test_one_blob} WHERE id = :id', array(':id' => $id))->fetchAssoc();
616 $this->assertTrue($r['blob1'] === $data, t('Can insert a blob: id @id, @data.', array('@id' => $id, '@data' => serialize($r))));
617 }
618
619
620
621
622 function testInsertMultipleBlob() {
623 $id = db_insert('test_two_blobs')
624 ->fields(array(
625 'blob1' => 'This is',
626 'blob2' => 'a test',
627 ))
628 ->execute();
629 $r = db_query('SELECT * FROM {test_two_blobs} WHERE id = :id', array(':id' => $id))->fetchAssoc();
630 $this->assertTrue($r['blob1'] === 'This is' && $r['blob2'] === 'a test', t('Can insert multiple blobs per row.'));
631 }
632 }
633
634
635
636
637 class DatabaseInsertDefaultsTestCase extends DatabaseTestCase {
638
639 public static function getInfo() {
640 return array(
641 'name' => 'Insert tests, default fields',
642 'description' => 'Test the Insert query builder with default values.',
643 'group' => 'Database',
644 );
645 }
646
647
648
649
650 function testDefaultInsert() {
651 $query = db_insert('test')->useDefaults(array('job'));
652 $id = $query->execute();
653
654 $schema = drupal_get_schema('test');
655
656 $job = db_query('SELECT job FROM {test} WHERE id = :id', array(':id' => $id))->fetchField();
657 $this->assertEqual($job, $schema['fields']['job']['default'], t('Default field value is set.'));
658 }
659
660
661
662
663 function testDefaultEmptyInsert() {
664 $num_records_before = (int) db_query('SELECT COUNT(*) FROM {test}')->fetchField();
665
666 try {
667 $result = db_insert('test')->execute();
668
669 $this->fail(t('Expected exception NoFieldsException has not been thrown.'));
670 } catch (NoFieldsException $e) {
671 $this->pass(t('Expected exception NoFieldsException has been thrown.'));
672 }
673
674 $num_records_after = (int) db_query('SELECT COUNT(*) FROM {test}')->fetchField();
675 $this->assertIdentical($num_records_before, $num_records_after, t('Do nothing as no fields are specified.'));
676 }
677
678
679
680
681 function testDefaultInsertWithFields() {
682 $query = db_insert('test')
683 ->fields(array('name' => 'Bob'))
684 ->useDefaults(array('job'));
685 $id = $query->execute();
686
687 $schema = drupal_get_schema('test');
688
689 $job = db_query('SELECT job FROM {test} WHERE id = :id', array(':id' => $id))->fetchField();
690 $this->assertEqual($job, $schema['fields']['job']['default'], t('Default field value is set.'));
691 }
692 }
693
694
695
696
697 class DatabaseUpdateTestCase extends DatabaseTestCase {
698
699 public static function getInfo() {
700 return array(
701 'name' => 'Update tests',
702 'description' => 'Test the Update query builder.',
703 'group' => 'Database',
704 );
705 }
706
707
708
709
710 function testSimpleUpdate() {
711 $num_updated = db_update('test')
712 ->fields(array('name' => 'Tiffany'))
713 ->condition('id', 1)
714 ->execute();
715 $this->assertIdentical($num_updated, 1, t('Updated 1 record.'));
716
717 $saved_name = db_query('SELECT name FROM {test} WHERE id = :id', array(':id' => 1))->fetchField();
718 $this->assertIdentical($saved_name, 'Tiffany', t('Updated name successfully.'));
719 }
720
721
722
723
724 function testSimpleNullUpdate() {
725 $this->ensureSampleDataNull();
726 $num_updated = db_update('test_null')
727 ->fields(array('age' => NULL))
728 ->condition('name', 'Kermit')
729 ->execute();
730 $this->assertIdentical($num_updated, 1, t('Updated 1 record.'));
731
732 $saved_age = db_query('SELECT age FROM {test_null} WHERE name = :name', array(':name' => 'Kermit'))->fetchField();
733 $this->assertNull($saved_age, t('Updated name successfully.'));
734 }
735
736
737
738
739 function testMultiUpdate() {
740 $num_updated = db_update('test')
741 ->fields(array('job' => 'Musician'))
742 ->condition('job', 'Singer')
743 ->execute();
744 $this->assertIdentical($num_updated, 2, t('Updated 2 records.'));
745
746 $num_matches = db_query('SELECT COUNT(*) FROM {test} WHERE job = :job', array(':job' => 'Musician'))->fetchField();
747 $this->assertIdentical($num_matches, '2', t('Updated fields successfully.'));
748 }
749
750
751
752
753 function testMultiGTUpdate() {
754 $num_updated = db_update('test')
755 ->fields(array('job' => 'Musician'))
756 ->condition('age', 26, '>')
757 ->execute();
758 $this->assertIdentical($num_updated, 2, t('Updated 2 records.'));
759
760 $num_matches = db_query('SELECT COUNT(*) FROM {test} WHERE job = :job', array(':job' => 'Musician'))->fetchField();
761 $this->assertIdentical($num_matches, '2', t('Updated fields successfully.'));
762 }
763
764
765
766
767 function testWhereUpdate() {
768 $num_updated = db_update('test')
769 ->fields(array('job' => 'Musician'))
770 ->where('age > :age', array(':age' => 26))
771 ->execute();
772 $this->assertIdentical($num_updated, 2, t('Updated 2 records.'));
773
774 $num_matches = db_query('SELECT COUNT(*) FROM {test} WHERE job = :job', array(':job' => 'Musician'))->fetchField();
775 $this->assertIdentical($num_matches, '2', t('Updated fields successfully.'));
776 }
777
778
779
780
781 function testWhereAndConditionUpdate() {
782 $update = db_update('test')
783 ->fields(array('job' => 'Musician'))
784 ->where('age > :age', array(':age' => 26))
785 ->condition('name', 'Ringo');
786 $num_updated = $update->execute();
787 $this->assertIdentical($num_updated, 1, t('Updated 1 record.'));
788
789 $num_matches = db_query('SELECT COUNT(*) FROM {test} WHERE job = :job', array(':job' => 'Musician'))->fetchField();
790 $this->assertIdentical($num_matches, '1', t('Updated fields successfully.'));
791 }
792
793
794
795
796 function testExpressionUpdate() {
797
798 db_update('test')
799 ->condition('id', 1)
800 ->fields(array('age' => 1))
801 ->execute();
802
803
804
805
806
807 $num_rows = db_update('test')
808 ->expression('age', 'age * age')
809 ->execute();
810 $this->assertIdentical($num_rows, 3, t('Number of affected rows are returned.'));
811 }
812 }
813
814
815
816
817 class DatabaseUpdateComplexTestCase extends DatabaseTestCase {
818
819 public static function getInfo() {
820 return array(
821 'name' => 'Update tests, Complex',
822 'description' => 'Test the Update query builder, complex queries.',
823 'group' => 'Database',
824 );
825 }
826
827
828
829
830 function testOrConditionUpdate() {
831 $update = db_update('test')
832 ->fields(array('job' => 'Musician'))
833 ->condition(db_or()
834 ->condition('name', 'John')
835 ->condition('name', 'Paul')
836 );
837 $num_updated = $update->execute();
838 $this->assertIdentical($num_updated, 2, t('Updated 2 records.'));
839
840 $num_matches = db_query('SELECT COUNT(*) FROM {test} WHERE job = :job', array(':job' => 'Musician'))->fetchField();
841 $this->assertIdentical($num_matches, '2', t('Updated fields successfully.'));
842 }
843
844
845
846
847 function testInConditionUpdate() {
848 $num_updated = db_update('test')
849 ->fields(array('job' => 'Musician'))
850 ->condition('name', array('John', 'Paul'), 'IN')
851 ->execute();
852 $this->assertIdentical($num_updated, 2, t('Updated 2 records.'));
853
854 $num_matches = db_query('SELECT COUNT(*) FROM {test} WHERE job = :job', array(':job' => 'Musician'))->fetchField();
855 $this->assertIdentical($num_matches, '2', t('Updated fields successfully.'));
856 }
857
858
859
860
861 function testNotInConditionUpdate() {
862
863
864 $num_updated = db_update('test')
865 ->fields(array('job' => 'Musician'))
866 ->condition('name', array('John', 'Paul', 'George'), 'NoT IN')
867 ->execute();
868 $this->assertIdentical($num_updated, 1, t('Updated 1 record.'));
869
870 $num_matches = db_query('SELECT COUNT(*) FROM {test} WHERE job = :job', array(':job' => 'Musician'))->fetchField();
871 $this->assertIdentical($num_matches, '1', t('Updated fields successfully.'));
872 }
873
874
875
876
877 function testBetweenConditionUpdate() {
878 $num_updated = db_update('test')
879 ->fields(array('job' => 'Musician'))
880 ->condition('age', array(25, 26), 'BETWEEN')
881 ->execute();
882 $this->assertIdentical($num_updated, 2, t('Updated 2 records.'));
883
884 $num_matches = db_query('SELECT COUNT(*) FROM {test} WHERE job = :job', array(':job' => 'Musician'))->fetchField();
885 $this->assertIdentical($num_matches, '2', t('Updated fields successfully.'));
886 }
887
888
889
890
891 function testLikeConditionUpdate() {
892 $num_updated = db_update('test')
893 ->fields(array('job' => 'Musician'))
894 ->condition('name', '%ge%', 'LIKE')
895 ->execute();
896 $this->assertIdentical($num_updated, 1, t('Updated 1 record.'));
897
898 $num_matches = db_query('SELECT COUNT(*) FROM {test} WHERE job = :job', array(':job' => 'Musician'))->fetchField();
899 $this->assertIdentical($num_matches, '1', t('Updated fields successfully.'));
900 }
901
902
903
904
905 function testUpdateExpression() {
906 $before_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'))->fetchField();
907 $GLOBALS['larry_test'] = 1;
908 $num_updated = db_update('test')
909 ->condition('name', 'Ringo')
910 ->fields(array('job' => 'Musician'))
911 ->expression('age', 'age + :age', array(':age' => 4))
912 ->execute();
913 $this->assertIdentical($num_updated, 1, t('Updated 1 record.'));
914
915 $num_matches = db_query('SELECT COUNT(*) FROM {test} WHERE job = :job', array(':job' => 'Musician'))->fetchField();
916 $this->assertIdentical($num_matches, '1', t('Updated fields successfully.'));
917
918 $person = db_query('SELECT * FROM {test} WHERE name = :name', array(':name' => 'Ringo'))->fetch();
919 $this->assertEqual($person->name, 'Ringo', t('Name set correctly.'));
920 $this->assertEqual($person->age, $before_age + 4, t('Age set correctly.'));
921 $this->assertEqual($person->job, 'Musician', t('Job set correctly.'));
922 $GLOBALS['larry_test'] = 0;
923 }
924
925
926
927
928 function testUpdateOnlyExpression() {
929 $before_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'))->fetchField();
930 $num_updated = db_update('test')
931 ->condition('name', 'Ringo')
932 ->expression('age', 'age + :age', array(':age' => 4))
933 ->execute();
934 $this->assertIdentical($num_updated, 1, t('Updated 1 record.'));
935
936 $after_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'))->fetchField();
937 $this->assertEqual($before_age + 4, $after_age, t('Age updated correctly'));
938 }
939 }
940
941
942
943
944 class DatabaseUpdateLOBTestCase extends DatabaseTestCase {
945
946 public static function getInfo() {
947 return array(
948 'name' => 'Update tests, LOB',
949 'description' => 'Test the Update query builder with LOB fields.',
950 'group' => 'Database',
951 );
952 }
953
954
955
956
957 function testUpdateOneBlob() {
958 $data = "This is\000a test.";
959 $this->assertTrue(strlen($data) === 15, t('Test data contains a NULL.'));
960 $id = db_insert('test_one_blob')
961 ->fields(array('blob1' => $data))
962 ->execute();
963
964 $data .= $data;
965 db_update('test_one_blob')
966 ->condition('id', $id)
967 ->fields(array('blob1' => $data))
968 ->execute();
969
970 $r = db_query('SELECT * FROM {test_one_blob} WHERE id = :id', array(':id' => $id))->fetchAssoc();
971 $this->assertTrue($r['blob1'] === $data, t('Can update a blob: id @id, @data.', array('@id' => $id, '@data' => serialize($r))));
972 }
973
974
975
976
977 function testUpdateMultipleBlob() {
978 $id = db_insert('test_two_blobs')
979 ->fields(array(
980 'blob1' => 'This is',
981 'blob2' => 'a test',
982 ))
983 ->execute();
984
985 db_update('test_two_blobs')
986 ->condition('id', $id)
987 ->fields(array('blob1' => 'and so', 'blob2' => 'is this'))
988 ->execute();
989
990 $r = db_query('SELECT * FROM {test_two_blobs} WHERE id = :id', array(':id' => $id))->fetchAssoc();
991 $this->assertTrue($r['blob1'] === 'and so' && $r['blob2'] === 'is this', t('Can update multiple blobs per row.'));
992 }
993 }
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006 class DatabaseDeleteTruncateTestCase extends DatabaseTestCase {
1007
1008 public static function getInfo() {
1009 return array(
1010 'name' => 'Delete/Truncate tests',
1011 'description' => 'Test the Delete and Truncate query builders.',
1012 'group' => 'Database',
1013 );
1014 }
1015
1016
1017
1018
1019 function testSubselectDelete() {
1020 $num_records_before = db_query('SELECT COUNT(*) FROM {test_task}')->fetchField();
1021 $pid_to_delete = db_query("SELECT * FROM {test_task} WHERE task = 'sleep'")->fetchField();
1022
1023 $subquery = db_select('test', 't')
1024 ->fields('t', array('id'))
1025 ->condition('t.id', array($pid_to_delete), 'IN');
1026 $delete = db_delete('test_task')
1027 ->condition('task', 'sleep')
1028 ->condition('pid', $subquery, 'IN');
1029
1030 $num_deleted = $delete->execute();
1031 $this->assertEqual($num_deleted, 1, t("Deleted 1 record."));
1032
1033 $num_records_after = db_query('SELECT COUNT(*) FROM {test_task}')->fetchField();
1034 $this->assertEqual($num_records_before, $num_records_after + $num_deleted, t('Deletion adds up.'));
1035 }
1036
1037
1038
1039
1040 function testSimpleDelete() {
1041 $num_records_before = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
1042
1043 $num_deleted = db_delete('test')
1044 ->condition('id', 1)
1045 ->execute();
1046 $this->assertIdentical($num_deleted, 1, t('Deleted 1 record.'));
1047
1048 $num_records_after = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
1049 $this->assertEqual($num_records_before, $num_records_after + $num_deleted, t('Deletion adds up.'));
1050 }
1051
1052
1053
1054
1055 function testTruncate() {
1056 $num_records_before = db_query("SELECT COUNT(*) FROM {test}")->fetchField();
1057
1058 db_truncate('test')->execute();
1059
1060 $num_records_after = db_query("SELECT COUNT(*) FROM {test}")->fetchField();
1061 $this->assertEqual(0, $num_records_after, t('Truncate really deletes everything.'));
1062 }
1063 }
1064
1065
1066
1067
1068 class DatabaseMergeTestCase extends DatabaseTestCase {
1069
1070 public static function getInfo() {
1071 return array(
1072 'name' => 'Merge tests',
1073 'description' => 'Test the Merge query builder.',
1074 'group' => 'Database',
1075 );
1076 }
1077
1078
1079
1080
1081 function testMergeInsert() {
1082 $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1083
1084 $result = db_merge('test_people')
1085 ->key(array('job' => 'Presenter'))
1086 ->fields(array(
1087 'age' => 31,
1088 'name' => 'Tiffany',
1089 ))
1090 ->execute();
1091
1092 $this->assertEqual($result, MergeQuery::STATUS_INSERT, t('Insert status returned.'));
1093
1094 $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1095 $this->assertEqual($num_records_before + 1, $num_records_after, t('Merge inserted properly.'));
1096
1097 $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Presenter'))->fetch();
1098 $this->assertEqual($person->name, 'Tiffany', t('Name set correctly.'));
1099 $this->assertEqual($person->age, 31, t('Age set correctly.'));
1100 $this->assertEqual($person->job, 'Presenter', t('Job set correctly.'));
1101 }
1102
1103
1104
1105
1106 function testMergeUpdate() {
1107 $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1108
1109 $result = db_merge('test_people')
1110 ->key(array('job' => 'Speaker'))
1111 ->fields(array(
1112 'age' => 31,
1113 'name' => 'Tiffany',
1114 ))
1115 ->execute();
1116
1117 $this->assertEqual($result, MergeQuery::STATUS_UPDATE, t('Update status returned.'));
1118
1119 $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1120 $this->assertEqual($num_records_before, $num_records_after, t('Merge updated properly.'));
1121
1122 $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
1123 $this->assertEqual($person->name, 'Tiffany', t('Name set correctly.'));
1124 $this->assertEqual($person->age, 31, t('Age set correctly.'));
1125 $this->assertEqual($person->job, 'Speaker', t('Job set correctly.'));
1126 }
1127
1128
1129
1130
1131 function testMergeUpdateExcept() {
1132 $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1133
1134 db_merge('test_people')
1135 ->key(array('job' => 'Speaker'))
1136 ->insertFields(array('age' => 31))
1137 ->updateFields(array('name' => 'Tiffany'))
1138 ->execute();
1139
1140 $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1141 $this->assertEqual($num_records_before, $num_records_after, t('Merge updated properly.'));
1142
1143 $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
1144 $this->assertEqual($person->name, 'Tiffany', t('Name set correctly.'));
1145 $this->assertEqual($person->age, 30, t('Age skipped correctly.'));
1146 $this->assertEqual($person->job, 'Speaker', t('Job set correctly.'));
1147 }
1148
1149
1150
1151
1152 function testMergeUpdateExplicit() {
1153 $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1154
1155 db_merge('test_people')
1156 ->key(array('job' => 'Speaker'))
1157 ->insertFields(array(
1158 'age' => 31,
1159 'name' => 'Tiffany',
1160 ))
1161 ->updateFields(array(
1162 'name' => 'Joe',
1163 ))
1164 ->execute();
1165
1166 $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1167 $this->assertEqual($num_records_before, $num_records_after, t('Merge updated properly.'));
1168
1169 $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
1170 $this->assertEqual($person->name, 'Joe', t('Name set correctly.'));
1171 $this->assertEqual($person->age, 30, t('Age skipped correctly.'));
1172 $this->assertEqual($person->job, 'Speaker', t('Job set correctly.'));
1173 }
1174
1175
1176
1177
1178 function testMergeUpdateExpression() {
1179 $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1180
1181 $age_before = db_query('SELECT age FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetchField();
1182
1183
1184
1185
1186
1187
1188 db_merge('test_people')
1189 ->key(array('job' => 'Speaker'))
1190 ->fields(array('name' => 'Tiffany'))
1191 ->insertFields(array('age' => 31))
1192 ->expression('age', 'age + :age', array(':age' => 4))
1193 ->execute();
1194
1195 $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1196 $this->assertEqual($num_records_before, $num_records_after, t('Merge updated properly.'));
1197
1198 $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
1199 $this->assertEqual($person->name, 'Tiffany', t('Name set correctly.'));
1200 $this->assertEqual($person->age, $age_before + 4, t('Age updated correctly.'));
1201 $this->assertEqual($person->job, 'Speaker', t('Job set correctly.'));
1202 }
1203
1204
1205
1206
1207 function testMergeInsertWithoutUpdate() {
1208 $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1209
1210 db_merge('test_people')
1211 ->key(array('job' => 'Presenter'))
1212 ->execute();
1213
1214 $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1215 $this->assertEqual($num_records_before + 1, $num_records_after, t('Merge inserted properly.'));
1216
1217 $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Presenter'))->fetch();
1218 $this->assertEqual($person->name, '', t('Name set correctly.'));
1219 $this->assertEqual($person->age, 0, t('Age set correctly.'));
1220 $this->assertEqual($person->job, 'Presenter', t('Job set correctly.'));
1221 }
1222
1223
1224
1225
1226 function testMergeUpdateWithoutUpdate() {
1227 $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1228
1229 db_merge('test_people')
1230 ->key(array('job' => 'Speaker'))
1231 ->execute();
1232
1233 $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1234 $this->assertEqual($num_records_before, $num_records_after, t('Merge skipped properly.'));
1235
1236 $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
1237 $this->assertEqual($person->name, 'Meredith', t('Name skipped correctly.'));
1238 $this->assertEqual($person->age, 30, t('Age skipped correctly.'));
1239 $this->assertEqual($person->job, 'Speaker', t('Job skipped correctly.'));
1240
1241 db_merge('test_people')
1242 ->key(array('job' => 'Speaker'))
1243 ->insertFields(array('age' => 31))
1244 ->execute();
1245
1246 $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
1247 $this->assertEqual($num_records_before, $num_records_after, t('Merge skipped properly.'));
1248
1249 $person = db_query('SELECT * FROM {test_people} WHERE job = :job', array(':job' => 'Speaker'))->fetch();
1250 $this->assertEqual($person->name, 'Meredith', t('Name skipped correctly.'));
1251 $this->assertEqual($person->age, 30, t('Age skipped correctly.'));
1252 $this->assertEqual($person->job, 'Speaker', t('Job skipped correctly.'));
1253 }
1254
1255
1256
1257
1258 function testInvalidMerge() {
1259 try {
1260
1261 db_merge('test_people')
1262 ->fields(array(
1263 'age' => 31,
1264 'name' => 'Tiffany',
1265 ))
1266 ->execute();
1267 }
1268 catch (InvalidMergeQueryException $e) {
1269 $this->pass(t('InvalidMergeQueryException thrown for invalid query.'));
1270 return;
1271 }
1272 $this->fail(t('No InvalidMergeQueryException thrown'));
1273 }
1274 }
1275
1276
1277
1278
1279 class DatabaseSelectTestCase extends DatabaseTestCase {
1280
1281 public static function getInfo() {
1282 return array(
1283 'name' => 'Select tests',
1284 'description' => 'Test the Select query builder.',
1285 'group' => 'Database',
1286 );
1287 }
1288
1289
1290
1291
1292 function testSimpleSelect() {
1293 $query = db_select('test');
1294 $name_field = $query->addField('test', 'name');
1295 $age_field = $query->addField('test', 'age', 'age');
1296 $result = $query->execute();
1297
1298 $num_records = 0;
1299 foreach ($result as $record) {
1300 $num_records++;
1301 }
1302
1303 $this->assertEqual($num_records, 4, t('Returned the correct number of rows.'));
1304 }
1305
1306
1307
1308
1309 function testSimpleComment() {
1310 $query = db_select('test')->comment('Testing query comments');
1311 $name_field = $query->addField('test', 'name');
1312 $age_field = $query->addField('test', 'age', 'age');
1313 $result = $query->execute();
1314
1315 $num_records = 0;
1316 foreach ($result as $record) {
1317 $num_records++;
1318 }
1319
1320 $query = (string)$query;
1321 $expected = " SELECT test.name AS name, test.age AS age\nFROM \n{test} test";
1322
1323 $this->assertEqual($num_records, 4, t('Returned the correct number of rows.'));
1324 $this->assertEqual($query, $expected, t('The flattened query contains the comment string.'));
1325 }
1326
1327
1328
1329
1330 function testVulnerableComment() {
1331 $query = db_select('test')->comment('Testing query comments */ SELECT nid FROM {node}; --');
1332 $name_field = $query->addField('test', 'name');
1333 $age_field = $query->addField('test', 'age', 'age');
1334 $result = $query->execute();
1335
1336 $num_records = 0;
1337 foreach ($result as $record) {
1338 $num_records++;
1339 }
1340
1341 $query = (string)$query;
1342 $expected = " SELECT test.name AS name, test.age AS age\nFROM \n{test} test";
1343
1344 $this->assertEqual($num_records, 4, t('Returned the correct number of rows.'));
1345 $this->assertEqual($query, $expected, t('The flattened query contains the sanitised comment string.'));
1346 }
1347
1348
1349
1350
1351 function testSimpleSelectConditional() {
1352 $query = db_select('test');
1353 $name_field = $query->addField('test', 'name');
1354 $age_field = $query->addField('test', 'age', 'age');
1355 $query->condition('age', 27);
1356 $result = $query->execute();
1357
1358
1359 $this->assertEqual($name_field, 'name', t('Name field alias is correct.'));
1360 $this->assertEqual($age_field, 'age', t('Age field alias is correct.'));
1361
1362
1363 $record = $result->fetch();
1364 $this->assertEqual($record->$name_field, 'George', t('Fetched name is correct.'));
1365 $this->assertEqual($record->$age_field, 27, t('Fetched age is correct.'));
1366 }
1367
1368
1369
1370
1371 function testSimpleSelectExpression() {
1372 $query = db_select('test');
1373 $name_field = $query->addField('test', 'name');
1374 $age_field = $query->addExpression("age*2", 'double_age');
1375 $query->condition('age', 27);
1376 $result = $query->execute();
1377
1378
1379 $this->assertEqual($name_field, 'name', t('Name field alias is correct.'));
1380 $this->assertEqual($age_field, 'double_age', t('Age field alias is correct.'));
1381
1382
1383 $record = $result->fetch();
1384 $this->assertEqual($record->$name_field, 'George', t('Fetched name is correct.'));
1385 $this->assertEqual($record->$age_field, 27*2, t('Fetched age expression is correct.'));
1386 }
1387
1388
1389
1390
1391 function testSimpleSelectExpressionMultiple() {
1392 $query = db_select('test');
1393 $name_field = $query->addField('test', 'name');
1394 $age_double_field = $query->addExpression("age*2");
1395 $age_triple_field = $query->addExpression("age*3");
1396 $query->condition('age', 27);
1397 $result = $query->execute();
1398
1399
1400 $this->assertEqual($age_double_field, 'expression', t('Double age field alias is correct.'));
1401 $this->assertEqual($age_triple_field, 'expression_2', t('Triple age field alias is correct.'));
1402
1403
1404 $record = $result->fetch();
1405 $this->assertEqual($record->$name_field, 'George', t('Fetched name is correct.'));
1406 $this->assertEqual($record->$age_double_field, 27*2, t('Fetched double age expression is correct.'));
1407 $this->assertEqual($record->$age_triple_field, 27*3, t('Fetched triple age expression is correct.'));
1408 }
1409
1410
1411
1412
1413 function testSimpleSelectMultipleFields() {
1414 $record = db_select('test')
1415 ->fields('test', array('id', 'name', 'age', 'job'))
1416 ->condition('age', 27)
1417 ->execute()->fetchObject();
1418
1419
1420 $this->assertNotNull($record->id, t('ID field is present.'));
1421 $this->assertNotNull($record->name, t('Name field is present.'));
1422 $this->assertNotNull($record->age, t('Age field is present.'));
1423 $this->assertNotNull($record->job, t('Job field is present.'));
1424
1425
1426
1427 $this->assertEqual($record->id, 2, t('ID field has the correct value.'));
1428 $this->assertEqual($record->name, 'George', t('Name field has the correct value.'));
1429 $this->assertEqual($record->age, 27, t('Age field has the correct value.'));
1430 $this->assertEqual($record->job, 'Singer', t('Job field has the correct value.'));
1431 }
1432
1433
1434
1435
1436 function testSimpleSelectAllFields() {
1437 $record = db_select('test')
1438 ->fields('test')
1439 ->condition('age', 27)
1440 ->execute()->fetchObject();
1441
1442
1443 $this->assertNotNull($record->id, t('ID field is present.'));
1444 $this->assertNotNull($record->name, t('Name field is present.'));
1445 $this->assertNotNull($record->age, t('Age field is present.'));
1446 $this->assertNotNull($record->job, t('Job field is present.'));
1447
1448
1449
1450 $this->assertEqual($record->id, 2, t('ID field has the correct value.'));
1451 $this->assertEqual($record->name, 'George', t('Name field has the correct value.'));
1452 $this->assertEqual($record->age, 27, t('Age field has the correct value.'));
1453 $this->assertEqual($record->job, 'Singer', t('Job field has the correct value.'));
1454 }
1455
1456
1457
1458
1459 function testNullCondition() {
1460 $this->ensureSampleDataNull();
1461
1462 $names = db_select('test_null', 'tn')
1463 ->fields('tn', array('name'))
1464 ->isNull('age')
1465 ->execute()->fetchCol();
1466
1467 $this->assertEqual(count($names), 1, t('Correct number of records found with NULL age.'));
1468 $this->assertEqual($names[0], 'Fozzie', t('Correct record returned for NULL age.'));
1469 }
1470
1471
1472
1473
1474 function testNotNullCondition() {
1475 $this->ensureSampleDataNull();
1476
1477 $names = db_select('test_null', 'tn')
1478 ->fields('tn', array('name'))
1479 ->isNotNull('tn.age')
1480 ->orderBy('name')
1481 ->execute()->fetchCol();
1482
1483 $this->assertEqual(count($names), 2, t('Correct number of records found withNOT NULL age.'));
1484 $this->assertEqual($names[0], 'Gonzo', t('Correct record returned for NOT NULL age.'));
1485 $this->assertEqual($names[1], 'Kermit', t('Correct record returned for NOT NULL age.'));
1486 }
1487
1488
1489
1490
1491
1492 function testUnion() {
1493 $query_1 = db_select('test', 't')
1494 ->fields('t', array('name'))
1495 ->condition('age', array(27, 28), 'IN');
1496
1497 $query_2 = db_select('test', 't')
1498 ->fields('t', array('name'))
1499 ->condition('age', 28);
1500
1501 $query_1->union($query_2);
1502
1503 $names = $query_1->execute()->fetchCol();
1504
1505
1506 $this->assertEqual(count($names), 2, t('UNION correctly discarded duplicates.'));
1507
1508 $this->assertEqual($names[0], 'George', t('First query returned correct name.'));
1509 $this->assertEqual($names[1], 'Ringo', t('Second query returned correct name.'));
1510 }
1511
1512
1513
1514
1515 function testUnionAll() {
1516 $query_1 = db_select('test', 't')
1517 ->fields('t', array('name'))
1518 ->condition('age', array(27, 28), 'IN');
1519
1520 $query_2 = db_select('test', 't')
1521 ->fields('t', array('name'))
1522 ->condition('age', 28);
1523
1524 $query_1->union($query_2, 'ALL');
1525
1526 $names = $query_1->execute()->fetchCol();
1527
1528
1529 $this->assertEqual(count($names), 3, t('UNION ALL correctly preserved duplicates.'));
1530
1531 $this->assertEqual($names[0], 'George', t('First query returned correct first name.'));
1532 $this->assertEqual($names[1], 'Ringo', t('Second query returned correct second name.'));
1533 $this->assertEqual($names[2], 'Ringo', t('Third query returned correct name.'));
1534 }
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551 function testRandomOrder() {
1552
1553
1554
1555 $number_of_items = 52;
1556 while (db_query("SELECT MAX(id) FROM {test}")->fetchField() < $number_of_items) {
1557 db_insert('test')->fields(array('name' => $this->randomName()))->execute();
1558 }
1559
1560
1561 $expected_ids = range(1, $number_of_items);
1562 $ordered_ids = db_select('test', 't')
1563 ->fields('t', array('id'))
1564 ->range(0, $number_of_items)
1565 ->orderBy('id')
1566 ->execute()
1567 ->fetchCol();
1568 $this->assertEqual($ordered_ids, $expected_ids, t('A query without random ordering returns IDs in the correct order.'));
1569
1570
1571
1572
1573 $randomized_ids = db_select('test', 't')
1574 ->fields('t', array('id'))
1575 ->range(0, $number_of_items)
1576 ->orderRandom()
1577 ->execute()
1578 ->fetchCol();
1579 $this->assertNotEqual($randomized_ids, $ordered_ids, t('A query with random ordering returns an unordered set of IDs.'));
1580 $sorted_ids = $randomized_ids;
1581 sort($sorted_ids);
1582 $this->assertEqual($sorted_ids, $ordered_ids, t('After sorting the random list, the result matches the original query.'));
1583
1584
1585
1586 $randomized_ids_second_set = db_select('test', 't')
1587 ->fields('t', array('id'))
1588 ->range(0, $number_of_items)
1589 ->orderRandom()
1590 ->execute()
1591 ->fetchCol();
1592 $this->assertNotEqual($randomized_ids_second_set, $randomized_ids, t('Performing the query with random ordering a second time returns IDs in a different order.'));
1593 $sorted_ids_second_set = $randomized_ids_second_set;
1594 sort($sorted_ids_second_set);
1595 $this->assertEqual($sorted_ids_second_set, $sorted_ids, t('After sorting the second random list, the result matches the sorted version of the first random list.'));
1596 }
1597
1598
1599
1600
1601 function testSelectDuplicateAlias() {
1602 $query = db_select('test', 't');
1603 $alias1 = $query->addField('t', 'name', 'the_alias');
1604 $alias2 = $query->addField('t', 'age', 'the_alias');
1605 $this->assertNotIdentical($alias1, $alias2, 'Duplicate aliases are renamed.');
1606 }
1607 }
1608
1609
1610
1611
1612 class DatabaseSelectSubqueryTestCase extends DatabaseTestCase {
1613
1614 public static function getInfo() {
1615 return array(
1616 'name' => 'Select tests, subqueries',
1617 'description' => 'Test the Select query builder.',
1618 'group' => 'Database',
1619 );
1620 }
1621
1622
1623
1624
1625 function testFromSubquerySelect() {
1626
1627 $subquery = db_select('test_task', 'tt');
1628 $subquery->addField('tt', 'pid', 'pid');
1629 $subquery->addField('tt', 'task', 'task');
1630 $subquery->condition('priority', 1);
1631
1632 for ($i = 0; $i < 2; $i++) {
1633
1634
1635 $select = db_select($subquery, 'tt2');
1636 $select->join('test', 't', 't.id=tt2.pid');
1637 $select->addField('t', 'name');
1638 if ($i) {
1639
1640
1641 $select->condition('name', 'John');
1642 }
1643 $select->condition('task', 'code');
1644
1645
1646
1647
1648
1649
1650 $people = $select->execute()->fetchCol();
1651
1652 $this->assertEqual(count($people), 1, t('Returned the correct number of rows.'));
1653 }
1654 }
1655
1656
1657
1658
1659 function testFromSubquerySelectWithLimit() {
1660
1661 $subquery = db_select('test_task', 'tt');
1662 $subquery->addField('tt', 'pid', 'pid');
1663 $subquery->addField('tt', 'task', 'task');
1664 $subquery->orderBy('priority', 'DESC');
1665 $subquery->range(0, 1);
1666
1667
1668
1669 $select = db_select($subquery, 'tt2');
1670 $select->join('test', 't', 't.id=tt2.pid');
1671 $select->addField('t', 'name');
1672
1673
1674
1675
1676
1677 $people = $select->execute()->fetchCol();
1678
1679 $this->assertEqual(count($people), 1, t('Returned the correct number of rows.'));
1680 }
1681
1682
1683
1684
1685 function testConditionSubquerySelect() {
1686
1687 $subquery = db_select('test_task', 'tt');
1688 $subquery->addField('tt', 'pid', 'pid');
1689 $subquery->condition('tt.priority', 1);
1690
1691
1692
1693 $select = db_select('test_task', 'tt2');
1694 $select->addField('tt2', 'task');
1695 $select->condition('tt2.pid', $subquery, 'IN');
1696
1697
1698
1699
1700
1701 $people = $select->execute()->fetchCol();
1702 $this->assertEqual(count($people), 5, t('Returned the correct number of rows.'));
1703 }
1704
1705
1706
1707
1708 function testJoinSubquerySelect() {
1709
1710 $subquery = db_select('test_task', 'tt');
1711 $subquery->addField('tt', 'pid', 'pid');
1712 $subquery->condition('priority', 1);
1713
1714
1715
1716 $select = db_select('test', 't');
1717 $select->join($subquery, 'tt', 't.id=tt.pid');
1718 $select->addField('t', 'name');
1719
1720
1721
1722
1723
1724 $people = $select->execute()->fetchCol();
1725
1726 $this->assertEqual(count($people), 2, t('Returned the correct number of rows.'));
1727 }
1728
1729
1730
1731
1732
1733
1734
1735 function testExistsSubquerySelect() {
1736
1737 db_insert('test_people')
1738 ->fields(array(
1739 'name' => 'George',
1740 'age' => 27,
1741 'job' => 'Singer',
1742 ))
1743 ->execute();
1744
1745 $query = db_select('test', 't')
1746 ->fields('t', array('name'));
1747
1748 $subquery = db_select('test_people', 'tp')
1749 ->fields('tp', array('name'))
1750 ->where('tp.name = t.name');
1751 $query->exists($subquery);
1752 $result = $query->execute();
1753
1754
1755 $record = $result->fetch();
1756 $this->assertEqual($record->name, 'George', t('Fetched name is correct using EXISTS query.'));
1757 }
1758
1759
1760
1761
1762
1763
1764
1765 function testNotExistsSubquerySelect() {
1766
1767 db_insert('test_people')
1768 ->fields(array(
1769 'name' => 'George',
1770 'age' => 27,
1771 'job' => 'Singer',
1772 ))
1773 ->execute();
1774
1775
1776 $query = db_select('test', 't')
1777 ->fields('t', array('name'));
1778
1779 $subquery = db_select('test_people', 'tp')
1780 ->fields('tp', array('name'))
1781 ->where('tp.name = t.name');
1782 $query->notExists($subquery);
1783
1784
1785 $people = $query->execute()->fetchCol();
1786 $this->assertEqual(count($people), 3, t('NOT EXISTS query returned the correct results.'));
1787 }
1788 }
1789
1790
1791
1792
1793 class DatabaseSelectOrderedTestCase extends DatabaseTestCase {
1794
1795 public static function getInfo() {
1796 return array(
1797 'name' => 'Select tests, ordered',
1798 'description' => 'Test the Select query builder.',
1799 'group' => 'Database',
1800 );
1801 }
1802
1803
1804
1805
1806 function testSimpleSelectOrdered() {
1807 $query = db_select('test');
1808 $name_field = $query->addField('test', 'name');
1809 $age_field = $query->addField('test', 'age', 'age');
1810 $query->orderBy($age_field);
1811 $result = $query->execute();
1812
1813 $num_records = 0;
1814 $last_age = 0;
1815 foreach ($result as $record) {
1816 $num_records++;
1817 $this->assertTrue($record->age >= $last_age, t('Results returned in correct order.'));
1818 $last_age = $record->age;
1819 }
1820
1821 $this->assertEqual($num_records, 4, t('Returned the correct number of rows.'));
1822 }
1823
1824
1825
1826
1827 function testSimpleSelectMultiOrdered() {
1828 $query = db_select('test');
1829 $name_field = $query->addField('test', 'name');
1830 $age_field = $query->addField('test', 'age', 'age');
1831 $job_field = $query->addField('test', 'job');
1832 $query->orderBy($job_field);
1833 $query->orderBy($age_field);
1834 $result = $query->execute();
1835
1836 $num_records = 0;
1837 $expected = array(
1838 array('Ringo', 28, 'Drummer'),
1839 array('John', 25, 'Singer'),
1840 array('George', 27, 'Singer'),
1841 array('Paul', 26, 'Songwriter'),
1842 );
1843 $results = $result->fetchAll(PDO::FETCH_NUM);
1844 foreach ($expected as $k => $record) {
1845 $num_records++;
1846 foreach ($record as $kk => $col) {
1847 if ($expected[$k][$kk] != $results[$k][$kk]) {
1848 $this->assertTrue(FALSE, t('Results returned in correct order.'));
1849 }
1850 }
1851 }
1852 $this->assertEqual($num_records, 4, t('Returned the correct number of rows.'));
1853 }
1854
1855
1856
1857
1858 function testSimpleSelectOrderedDesc() {
1859 $query = db_select('test');
1860 $name_field = $query->addField('test', 'name');
1861 $age_field = $query->addField('test', 'age', 'age');
1862 $query->orderBy($age_field, 'DESC');
1863 $result = $query->execute();
1864
1865 $num_records = 0;
1866 $last_age = 100000000;
1867 foreach ($result as $record) {
1868 $num_records++;
1869 $this->assertTrue($record->age <= $last_age, t('Results returned in correct order.'));
1870 $last_age = $record->age;
1871 }
1872
1873 $this->assertEqual($num_records, 4, t('Returned the correct number of rows.'));
1874 }
1875 }
1876
1877
1878
1879
1880 class DatabaseSelectComplexTestCase extends DatabaseTestCase {
1881
1882 public static function getInfo() {
1883 return array(
1884 'name' => 'Select tests, complex',
1885 'description' => 'Test the Select query builder with more complex queries.',
1886 'group' => 'Database',
1887 );
1888 }
1889
1890
1891
1892
1893 function testDefaultJoin() {
1894 $query = db_select('test_task', 't');
1895 $people_alias = $query->join('test', 'p', 't.pid = p.id');
1896 $name_field = $query->addField($people_alias, 'name', 'name');
1897 $task_field = $query->addField('t', 'task', 'task');
1898 $priority_field = $query->addField('t', 'priority', 'priority');
1899
1900 $query->orderBy($priority_field);
1901 $result = $query->execute();
1902
1903 $num_records = 0;
1904 $last_priority = 0;
1905 foreach ($result as $record) {
1906 $num_records++;
1907 $this->assertTrue($record->$priority_field >= $last_priority, t('Results returned in correct order.'));
1908 $this->assertNotEqual($record->$name_field, 'Ringo', t('Taskless person not selected.'));
1909 $last_priority = $record->$priority_field;
1910 }
1911
1912 $this->assertEqual($num_records, 7, t('Returned the correct number of rows.'));
1913 }
1914
1915
1916
1917
1918 function testLeftOuterJoin() {
1919 $query = db_select('test', 'p');
1920 $people_alias = $query->leftJoin('test_task', 't', 't.pid = p.id');
1921 $name_field = $query->addField('p', 'name', 'name');
1922 $task_field = $query->addField($people_alias, 'task', 'task');
1923 $priority_field = $query->addField($people_alias, 'priority', 'priority');
1924
1925 $query->orderBy($name_field);
1926 $result = $query->execute();
1927
1928 $num_records = 0;
1929 $last_name = 0;
1930
1931 foreach ($result as $record) {
1932 $num_records++;
1933 $this->assertTrue(strcmp($record->$name_field, $last_name) >= 0, t('Results returned in correct order.'));
1934 $last_priority = $record->$name_field;
1935 }
1936
1937 $this->assertEqual($num_records, 8, t('Returned the correct number of rows.'));
1938 }
1939
1940
1941
1942
1943 function testGroupBy() {
1944 $query = db_select('test_task', 't');
1945 $count_field = $query->addExpression('COUNT(task)', 'num');
1946 $task_field = $query->addField('t', 'task');
1947 $query->orderBy($count_field);
1948 $query->groupBy($task_field);
1949 $result = $query->execute();
1950
1951 $num_records = 0;
1952 $last_count = 0;
1953 $records = array();
1954 foreach ($result as $record) {
1955 $num_records++;
1956 $this->assertTrue($record->$count_field >= $last_count, t('Results returned in correct order.'));
1957 $last_count = $record->$count_field;
1958 $records[$record->$task_field] = $record->$count_field;
1959 }
1960
1961 $correct_results = array(
1962 'eat' => 1,
1963 'sleep' => 2,
1964 'code' => 1,
1965 'found new band' => 1,
1966 'perform at superbowl' => 1,
1967 );
1968
1969 foreach ($correct_results as $task => $count) {
1970 $this->assertEqual($records[$task], $count, t("Correct number of '@task' records found.", array('@task' => $task)));
1971 }
1972
1973 $this->assertEqual($num_records, 6, t('Returned the correct number of total rows.'));
1974 }
1975
1976
1977
1978
1979 function testGroupByAndHaving() {
1980 $query = db_select('test_task', 't');
1981 $count_field = $query->addExpression('COUNT(task)', 'num');
1982 $task_field = $query->addField('t', 'task');
1983 $query->orderBy($count_field);
1984 $query->groupBy($task_field);
1985 $query->having('COUNT(task) >= 2');
1986 $result = $query->execute();
1987
1988 $num_records = 0;
1989 $last_count = 0;
1990 $records = array();
1991 foreach ($result as $record) {
1992 $num_records++;
1993 $this->assertTrue($record->$count_field >= 2, t('Record has the minimum count.'));
1994 $this->assertTrue($record->$count_field >= $last_count, t('Results returned in correct order.'));
1995 $last_count = $record->$count_field;
1996 $records[$record->$task_field] = $record->$count_field;
1997 }
1998
1999 $correct_results = array(
2000 'sleep' => 2,
2001 );
2002
2003 foreach ($correct_results as $task => $count) {
2004 $this->assertEqual($records[$task], $count, t("Correct number of '@task' records found.", array('@task' => $task)));
2005 }
2006
2007 $this->assertEqual($num_records, 1, t('Returned the correct number of total rows.'));
2008 }
2009
2010
2011
2012
2013 function testRange() {
2014 $query = db_select('test');
2015 $name_field = $query->addField('test', 'name');
2016 $age_field = $query->addField('test', 'age', 'age');
2017 $query->range(0, 2);
2018 $result = $query->execute();
2019
2020 $num_records = 0;
2021 foreach ($result as $record) {
2022 $num_records++;
2023 }
2024
2025 $this->assertEqual($num_records, 2, t('Returned the correct number of rows.'));
2026 }
2027
2028
2029
2030
2031 function testDistinct() {
2032 $query = db_select('test_task');
2033 $task_field = $query->addField('test_task', 'task');
2034 $query->distinct();
2035 $result = $query->execute();
2036
2037 $num_records = 0;
2038 foreach ($result as $record) {
2039 $num_records++;
2040 }
2041
2042 $this->assertEqual($num_records, 6, t('Returned the correct number of rows.'));
2043 }
2044
2045
2046
2047
2048 function testCountQuery() {
2049 $query = db_select('test');
2050 $name_field = $query->addField('test', 'name');
2051 $age_field = $query->addField('test', 'age', 'age');
2052 $query->orderBy('name');
2053
2054 $count = $query->countQuery()->execute()->fetchField();
2055
2056 $this->assertEqual($count, 4, t('Counted the correct number of records.'));
2057
2058
2059
2060 $record = $query->execute()->fetch();
2061 $this->assertEqual($record->$name_field, 'George', t('Correct data retrieved.'));
2062 $this->assertEqual($record->$age_field, 27, t('Correct data retrieved.'));
2063 }
2064
2065 function testHavingCountQuery() {
2066 $query = db_select('test')
2067 ->extend('PagerDefault')
2068 ->groupBy('age')
2069 ->having('age + 1 > 0');
2070 $query->addField('test', 'age');
2071 $query->addExpression('age + 1');
2072 $count = count($query->execute()->fetchCol());
2073 $this->assertEqual($count, 4, t('Counted the correct number of records.'));
2074 }
2075
2076
2077
2078
2079
2080 function testCountQueryRemovals() {
2081 $query = db_select('test');
2082 $query->fields('test');
2083 $query->orderBy('name');
2084 $count = $query->countQuery();
2085
2086
2087 $tables = $query->getTables();
2088 $this->assertEqual($tables['test']['all_fields'], 1, t('Query correctly sets \'all_fields\' statement.'));
2089 $tables = $count->getTables();
2090 $this->assertFalse(isset($tables['test']['all_fields']), t('Count query correctly unsets \'all_fields\' statement.'));
2091
2092
2093 $orderby = $query->getOrderBy();
2094 $this->assertEqual($orderby['name'], 'ASC', t('Query correctly sets ordering clause.'));
2095 $orderby = $count->getOrderBy();
2096 $this->assertFalse(isset($orderby['name']), t('Count query correctly unsets ordering caluse.'));
2097
2098
2099 $count = $count->execute()->fetchField();
2100
2101 $this->assertEqual($count, 4, t('Counted the correct number of records.'));
2102 }
2103
2104
2105
2106
2107
2108 function testCountQueryFieldRemovals() {
2109
2110
2111
2112
2113
2114 $query = db_select('test');
2115 $query->fields('test', array('fail'));
2116 $this->assertEqual(4, $query->countQuery()->execute()->fetchField(), t('Count Query removed fields'));
2117
2118 $query = db_select('test');
2119 $query->addExpression('fail');
2120 $this->assertEqual(4, $query->countQuery()->execute()->fetchField(), t('Count Query removed expressions'));
2121 }
2122
2123
2124
2125
2126 function testCountQueryDistinct() {
2127 $query = db_select('test_task');
2128 $task_field = $query->addField('test_task', 'task');
2129 $query->distinct();
2130
2131 $count = $query->countQuery()->execute()->fetchField();
2132
2133 $this->assertEqual($count, 6, t('Counted the correct number of records.'));
2134 }
2135
2136
2137
2138
2139 function testCountQueryGroupBy() {
2140 $query = db_select('test_task');
2141 $pid_field = $query->addField('test_task', 'pid');
2142 $query->groupBy('pid');
2143
2144 $count = $query->countQuery()->execute()->fetchField();
2145
2146 $this->assertEqual($count, 3, t('Counted the correct number of records.'));
2147
2148
2149
2150 $query = db_select('test_task');
2151 $pid_field = $query->addField('test_task', 'pid', 'pid_alias');
2152 $query->addExpression('COUNT(test_task.task)', 'count');
2153 $query->groupBy('pid_alias');
2154 $query->orderBy('pid_alias', 'asc');
2155
2156 $count = $query->countQuery()->execute()->fetchField();
2157
2158 $this->assertEqual($count, 3, t('Counted the correct number of records.'));
2159 }
2160
2161
2162
2163
2164 function testNestedConditions() {
2165
2166
2167
2168
2169 $query = db_select('test');
2170 $query->addField('test', 'job');
2171 $query->condition('name', 'Paul');
2172 $query->condition(db_or()->condition('age', 26)->condition('age', 27));
2173
2174 $job = $query->execute()->fetchField();
2175 $this->assertEqual($job, 'Songwriter', t('Correct data retrieved.'));
2176 }
2177
2178
2179
2180
2181 function testJoinTwice() {
2182 $query = db_select('test')->fields('test');
2183 $alias = $query->join('test', 'test', 'test.job = %alias.job');
2184 $query->addField($alias, 'name', 'othername');
2185 $query->addField($alias, 'job', 'otherjob');
2186 $query->where("$alias.name <> test.name");
2187 $crowded_job = $query->execute()->fetch();
2188 $this->assertEqual($crowded_job->job, $crowded_job->otherjob, t('Correctly joined same table twice.'));
2189 $this->assertNotEqual($crowded_job->name, $crowded_job->othername, t('Correctly joined same table twice.'));
2190 }
2191
2192 }
2193
2194
2195
2196
2197 class DatabaseSelectComplexTestCase2 extends DatabaseTestCase {
2198
2199 public static function getInfo() {
2200 return array(
2201 'name' => 'Select tests, complex 2',
2202 'description' => 'Test the Select query builder with even more complex queries.',
2203 'group' => 'Database',
2204 );
2205 }
2206
2207 function setUp() {
2208 DrupalWebTestCase::setUp('database_test', 'node_access_test');
2209
2210 $schema['test'] = drupal_get_schema('test');
2211 $schema['test_people'] = drupal_get_schema('test_people');
2212 $schema['test_one_blob'] = drupal_get_schema('test_one_blob');
2213 $schema['test_two_blobs'] = drupal_get_schema('test_two_blobs');
2214 $schema['test_task'] = drupal_get_schema('test_task');
2215
2216 $this->installTables($schema);
2217
2218 $this->addSampleData();
2219 }
2220
2221
2222
2223
2224 function testJoinSubquery() {
2225 $acct = $this->drupalCreateUser(array('access content'));
2226 $this->drupalLogin($acct);
2227
2228 $query = db_select('test_task', 'tt', array('target' => 'slave'));
2229 $query->addExpression('tt.pid + 1', 'abc');
2230 $query->condition('priority', 1, '>');
2231 $query->condition('priority', 100, '<');
2232
2233 $subquery = db_select('test', 'tp');
2234 $subquery->join('test_one_blob', 'tpb', 'tp.id = tpb.id');
2235 $subquery->join('node', 'n', 'tp.id = n.nid');
2236 $subquery->addTag('node_access');
2237 $subquery->addMetaData('account', $acct);
2238 $subquery->addField('tp', 'id');
2239 $subquery->condition('age', 5, '>');
2240 $subquery->condition('age', 500, '<');
2241
2242 $query->leftJoin($subquery, 'sq', 'tt.pid = sq.id');
2243 $query->join('test_one_blob', 'tb3', 'tt.pid = tb3.id');
2244
2245
2246
2247 $query->preExecute();
2248 $query->getArguments();
2249 $str = (string) $query;
2250
2251
2252 $pos = strpos($str, 'db_condition_placeholder_0', 0);
2253 $pos2 = strpos($str, 'db_condition_placeholder_0', $pos + 1);
2254 $this->assertFalse($pos2, "Condition placeholder is not repeated");
2255 }
2256 }
2257
2258 class DatabaseSelectPagerDefaultTestCase extends DatabaseTestCase {
2259
2260 public static function getInfo() {
2261 return array(
2262 'name' => 'Pager query tests',
2263 'description' => 'Test the pager query extender.',
2264 'group' => 'Database',
2265 );
2266 }
2267
2268
2269
2270
2271
2272
2273
2274 function testEvenPagerQuery() {
2275
2276
2277
2278
2279 $limit = 2;
2280 $count = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
2281
2282 $correct_number = $limit;
2283 $num_pages = floor($count / $limit);
2284
2285
2286 if (!($num_pages * $limit < $count)) {
2287 $num_pages--;
2288 }
2289
2290 for ($page = 0; $page <= $num_pages; ++$page) {
2291 $this->drupalGet('database_test/pager_query_even/' . $limit, array('query' => array('page' => $page)));
2292 $data = json_decode($this->drupalGetContent());
2293
2294 if ($page == $num_pages) {
2295 $correct_number = $count - ($limit * $page);
2296 }
2297
2298 $this->assertEqual(count($data->names), $correct_number, t('Correct number of records returned by pager: @number', array('@number' => $correct_number)));
2299 }
2300 }
2301
2302
2303
2304
2305
2306
2307
2308 function testOddPagerQuery() {
2309
2310
2311
2312
2313 $limit = 2;
2314 $count = db_query('SELECT COUNT(*) FROM {test_task}')->fetchField();
2315
2316 $correct_number = $limit;
2317 $num_pages = floor($count / $limit);
2318
2319
2320 if (!($num_pages * $limit < $count)) {
2321 $num_pages--;
2322 }
2323
2324 for ($page = 0; $page <= $num_pages; ++$page) {
2325 $this->drupalGet('database_test/pager_query_odd/' . $limit, array('query' => array('page' => $page)));
2326 $data = json_decode($this->drupalGetContent());
2327
2328 if ($page == $num_pages) {
2329 $correct_number = $count - ($limit * $page);
2330 }
2331
2332 $this->assertEqual(count($data->names), $correct_number, t('Correct number of records returned by pager: @number', array('@number' => $correct_number)));
2333 }
2334 }
2335
2336
2337
2338
2339
2340
2341 function testInnerPagerQuery() {
2342 $query = db_select('test', 't')->extend('PagerDefault');
2343 $query
2344 ->fields('t', array('age'))
2345 ->orderBy('age')
2346 ->limit(5);
2347
2348 $outer_query = db_select($query);
2349 $outer_query->addField('subquery', 'age');
2350
2351 $ages = $outer_query
2352 ->execute()
2353 ->fetchCol();
2354 $this->assertEqual($ages, array(25, 26, 27, 28), t('Inner pager query returned the correct ages.'));
2355 }
2356
2357
2358
2359
2360
2361
2362 function testHavingPagerQuery() {
2363 $query = db_select('test', 't')->extend('PagerDefault');
2364 $query
2365 ->fields('t', array('name'))
2366 ->orderBy('name')
2367 ->groupBy('name')
2368 ->having('MAX(age) > :count', array(':count' => 26))
2369 ->limit(5);
2370
2371 $ages = $query
2372 ->execute()
2373 ->fetchCol();
2374 $this->assertEqual($ages, array('George', 'Ringo'), t('Pager query with having expression returned the correct ages.'));
2375 }
2376
2377
2378
2379
2380 function testElementNumbers() {
2381 $_GET['page'] = '3, 2, 1, 0';
2382
2383 $name = db_select('test', 't')->extend('PagerDefault')
2384 ->element(2)
2385 ->fields('t', array('name'))
2386 ->orderBy('age')
2387 ->limit(1)
2388 ->execute()
2389 ->fetchField();
2390 $this->assertEqual($name, 'Paul', t('Pager query #1 with a specified element ID returned the correct results.'));
2391
2392
2393
2394 $name = db_select('test', 't')->extend('PagerDefault')
2395 ->element(1)
2396 ->fields('t', array('name'))
2397 ->orderBy('age')
2398 ->limit(1)
2399 ->execute()
2400 ->fetchField();
2401 $this->assertEqual($name, 'George', t('Pager query #2 with a specified element ID returned the correct results.'));
2402
2403 $name = db_select('test', 't')->extend('PagerDefault')
2404 ->fields('t', array('name'))
2405 ->orderBy('age')
2406 ->limit(1)
2407 ->execute()
2408 ->fetchField();
2409 $this->assertEqual($name, 'John', t('Pager query #3 with a generated element ID returned the correct results.'));
2410
2411 unset($_GET['page']);
2412 }
2413 }
2414
2415
2416 class DatabaseSelectTableSortDefaultTestCase extends DatabaseTestCase {
2417
2418 public static function getInfo() {
2419 return array(
2420 'name' => 'Tablesort query tests',
2421 'description' => 'Test the tablesort query extender.',
2422 'group' => 'Database',
2423 );
2424 }
2425
2426
2427
2428
2429
2430
2431
2432 function testTableSortQuery() {
2433 $sorts = array(
2434 array('field' => t('Task ID'), 'sort' => 'desc', 'first' => 'perform at superbowl', 'last' => 'eat'),
2435 array('field' => t('Task ID'), 'sort' => 'asc', 'first' => 'eat', 'last' => 'perform at superbowl'),
2436 array('field' => t('Task'), 'sort' => 'asc', 'first' => 'code', 'last' => 'sleep'),
2437 array('field' => t('Task'), 'sort' => 'desc', 'first' => 'sleep', 'last' => 'code'),
2438
2439
2440 );
2441
2442 foreach ($sorts as $sort) {
2443 $this->drupalGet('database_test/tablesort/', array('query' => array('order' => $sort['field'], 'sort' => $sort['sort'])));
2444 $data = json_decode($this->drupalGetContent());
2445
2446 $first = array_shift($data->tasks);
2447 $last = array_pop($data->tasks);
2448
2449 $this->assertEqual($first->task, $sort['first'], t('Items appear in the correct order.'));
2450 $this->assertEqual($last->task, $sort['last'], t('Items appear in the correct order.'));
2451 }
2452 }
2453
2454
2455
2456
2457
2458 function testTableSortQueryFirst() {
2459 $sorts = array(
2460 array('field' => t('Task ID'), 'sort' => 'desc', 'first' => 'perform at superbowl', 'last' => 'eat'),
2461 array('field' => t('Task ID'), 'sort' => 'asc', 'first' => 'eat', 'last' => 'perform at superbowl'),
2462 array('field' => t('Task'), 'sort' => 'asc', 'first' => 'code', 'last' => 'sleep'),
2463 array('field' => t('Task'), 'sort' => 'desc', 'first' => 'sleep', 'last' => 'code'),
2464
2465
2466 );
2467
2468 foreach ($sorts as $sort) {
2469 $this->drupalGet('database_test/tablesort_first/', array('query' => array('order' => $sort['field'], 'sort' => $sort['sort'])));
2470 $data = json_decode($this->drupalGetContent());
2471
2472 $first = array_shift($data->tasks);
2473 $last = array_pop($data->tasks);
2474
2475 $this->assertEqual($first->task, $sort['first'], t('Items appear in the correct order sorting by @field @sort.', array('@field' => $sort['field'], '@sort' => $sort['sort'])));
2476 $this->assertEqual($last->task, $sort['last'], t('Items appear in the correct order sorting by @field @sort.', array('@field' => $sort['field'], '@sort' => $sort['sort'])));
2477 }
2478 }
2479
2480
2481
2482
2483 function testTableSortDefaultSort() {
2484 $this->drupalGet('database_test/tablesort_default_sort');
2485
2486
2487 }
2488 }
2489
2490
2491
2492
2493
2494
2495
2496 class DatabaseTaggingTestCase extends DatabaseTestCase {
2497
2498 public static function getInfo() {
2499 return array(
2500 'name' => 'Query tagging tests',
2501 'description' => 'Test the tagging capabilities of the Select builder.',
2502 'group' => 'Database',
2503 );
2504 }
2505
2506
2507
2508
2509 function testHasTag() {
2510 $query = db_select('test');
2511 $query->addField('test', 'name');
2512 $query->addField('test', 'age', 'age');
2513
2514 $query->addTag('test');
2515
2516 $this->assertTrue($query->hasTag('test'), t('hasTag() returned true.'));
2517 $this->assertFalse($query->hasTag('other'), t('hasTag() returned false.'));
2518 }
2519
2520
2521
2522
2523 function testHasAllTags() {
2524 $query = db_select('test');
2525 $query->addField('test', 'name');
2526 $query->addField('test', 'age', 'age');
2527
2528 $query->addTag('test');
2529 $query->addTag('other');
2530
2531 $this->assertTrue($query->hasAllTags('test', 'other'), t('hasAllTags() returned true.'));
2532 $this->assertFalse($query->hasAllTags('test', 'stuff'), t('hasAllTags() returned false.'));
2533 }
2534
2535
2536
2537
2538 function testHasAnyTag() {
2539 $query = db_select('test');
2540 $query->addField('test', 'name');
2541 $query->addField('test', 'age', 'age');
2542
2543 $query->addTag('test');
2544
2545 $this->assertTrue($query->hasAnyTag('test', 'other'), t('hasAnyTag() returned true.'));
2546 $this->assertFalse($query->hasAnyTag('other', 'stuff'), t('hasAnyTag() returned false.'));
2547 }
2548
2549
2550
2551
2552
2553
2554 function testMetaData() {
2555 $query = db_select('test');
2556 $query->addField('test', 'name');
2557 $query->addField('test', 'age', 'age');
2558
2559 $data = array(
2560 'a' => 'A',
2561 'b' => 'B',
2562 );
2563
2564 $query->addMetaData('test', $data);
2565
2566 $return = $query->getMetaData('test');
2567 $this->assertEqual($data, $return, t('Corect metadata returned.'));
2568
2569 $return = $query->getMetaData('nothere');
2570 $this->assertNull($return, t('Non-existent key returned NULL.'));
2571 }
2572 }
2573
2574
2575
2576
2577
2578
2579 class DatabaseAlterTestCase extends DatabaseTestCase {
2580
2581 public static function getInfo() {
2582 return array(
2583 'name' => 'Query altering tests',
2584 'description' => 'Test the hook_query_alter capabilities of the Select builder.',
2585 'group' => 'Database',
2586 );
2587 }
2588
2589
2590
2591
2592 function testSimpleAlter() {
2593 $query = db_select('test');
2594 $query->addField('test', 'name');
2595 $query->addField('test', 'age', 'age');
2596 $query->addTag('database_test_alter_add_range');
2597
2598 $result = $query->execute();
2599
2600 $num_records = 0;
2601 foreach ($result as $record) {
2602 $num_records++;
2603 }
2604
2605 $this->assertEqual($num_records, 2, t('Returned the correct number of rows.'));
2606 }
2607
2608
2609
2610
2611 function testAlterWithJoin() {
2612 $query = db_select('test_task');
2613 $tid_field = $query->addField('test_task', 'tid');
2614 $task_field = $query->addField('test_task', 'task');
2615 $query->orderBy($task_field);
2616 $query->addTag('database_test_alter_add_join');
2617
2618 $result = $query->execute();
2619
2620 $records = $result->fetchAll();
2621
2622 $this->assertEqual(count($records), 2, t('Returned the correct number of rows.'));
2623
2624 $this->assertEqual($records[0]->name, 'George', t('Correct data retrieved.'));
2625 $this->assertEqual($records[0]->$tid_field, 4, t('Correct data retrieved.'));
2626 $this->assertEqual($records[0]->$task_field, 'sing', t('Correct data retrieved.'));
2627 $this->assertEqual($records[1]->name, 'George', t('Correct data retrieved.'));
2628 $this->assertEqual($records[1]->$tid_field, 5, t('Correct data retrieved.'));
2629 $this->assertEqual($records[1]->$task_field, 'sleep', t('Correct data retrieved.'));
2630 }
2631
2632
2633
2634
2635 function testAlterChangeConditional() {
2636 $query = db_select('test_task');
2637 $tid_field = $query->addField('test_task', 'tid');
2638 $pid_field = $query->addField('test_task', 'pid');
2639 $task_field = $query->addField('test_task', 'task');
2640 $people_alias = $query->join('test', 'people', "test_task.pid = people.id");
2641 $name_field = $query->addField($people_alias, 'name', 'name');
2642 $query->condition('test_task.tid', '1');
2643 $query->orderBy($tid_field);
2644 $query->addTag('database_test_alter_change_conditional');
2645
2646 $result = $query->execute();
2647
2648 $records = $result->fetchAll();
2649
2650 $this->assertEqual(count($records), 1, t('Returned the correct number of rows.'));
2651 $this->assertEqual($records[0]->$name_field, 'John', t('Correct data retrieved.'));
2652 $this->assertEqual($records[0]->$tid_field, 2, t('Correct data retrieved.'));
2653 $this->assertEqual($records[0]->$pid_field, 1, t('Correct data retrieved.'));
2654 $this->assertEqual($records[0]->$task_field, 'sleep', t('Correct data retrieved.'));
2655 }
2656
2657
2658
2659
2660 function testAlterChangeFields() {
2661 $query = db_select('test');
2662 $name_field = $query->addField('test', 'name');
2663 $age_field = $query->addField('test', 'age', 'age');
2664 $query->orderBy('name');
2665 $query->addTag('database_test_alter_change_fields');
2666
2667 $record = $query->execute()->fetch();
2668 $this->assertEqual($record->$name_field, 'George', t('Correct data retrieved.'));
2669 $this->assertFalse(isset($record->$age_field), t('Age field not found, as intended.'));
2670 }
2671
2672
2673
2674
2675 function testAlterExpression() {
2676 $query = db_select('test');
2677 $name_field = $query->addField('test', 'name');
2678 $age_field = $query->addExpression("age*2", 'double_age');
2679 $query->condition('age', 27);
2680 $query->addTag('database_test_alter_change_expressions');
2681 $result = $query->execute();
2682
2683
2684 $record = $result->fetch();
2685
2686 $this->assertEqual($record->$name_field, 'George', t('Fetched name is correct.'));
2687 $this->assertEqual($record->$age_field, 27*3, t('Fetched age expression is correct.'));
2688 }
2689
2690
2691
2692
2693 function testAlterRemoveRange() {
2694 $query = db_select('test');
2695 $query->addField('test', 'name');
2696 $query->addField('test', 'age', 'age');
2697 $query->range(0, 2);
2698 $query->addTag('database_test_alter_remove_range');
2699
2700 $num_records = count($query->execute()->fetchAll());
2701
2702 $this->assertEqual($num_records, 4, t('Returned the correct number of rows.'));
2703 }
2704
2705
2706
2707
2708 function testSimpleAlterSubquery() {
2709
2710 $subquery = db_select('test', 'p');
2711 $subquery->addField('p', 'name');
2712 $subquery->addField('p', 'id');
2713
2714 $subquery->condition('age', 27);
2715 $subquery->addExpression("age*2", 'double_age');
2716
2717 $subquery->addTag('database_test_alter_change_expressions');
2718
2719
2720 $query = db_select('test_task', 'tt');
2721 $query->join($subquery, 'pq', 'pq.id = tt.pid');
2722 $age_field = $query->addField('pq', 'double_age');
2723 $name_field = $query->addField('pq', 'name');
2724
2725 $record = $query->execute()->fetch();
2726 $this->assertEqual($record->$name_field, 'George', t('Fetched name is correct.'));
2727 $this->assertEqual($record->$age_field, 27*3, t('Fetched age expression is correct.'));
2728 }
2729 }
2730
2731
2732
2733
2734 class DatabaseRegressionTestCase extends DatabaseTestCase {
2735
2736 public static function getInfo() {
2737 return array(
2738 'name' => 'Regression tests',
2739 'description' => 'Regression tests cases for the database layer.',
2740 'group' => 'Database',
2741 );
2742 }
2743
2744
2745
2746
2747
2748
2749
2750 function testRegression_310447() {
2751
2752 $name = str_repeat("é", 255);
2753 db_insert('test')
2754 ->fields(array(
2755 'name' => $name,
2756 'age' => 20,
2757 'job' => 'Dancer',
2758 ))->execute();
2759
2760 $from_database = db_query('SELECT name FROM {test} WHERE name = :name', array(':name' => $name))->fetchField();
2761 $this->assertIdentical($name, $from_database, t("The database handles UTF-8 characters cleanly."));
2762 }
2763
2764
2765
2766
2767 function testDBTableExists() {
2768 $this->assertIdentical(TRUE, db_table_exists('node'), t('Returns true for existent table.'));
2769 $this->assertIdentical(FALSE, db_table_exists('nosuchtable'), t('Returns false for nonexistent table.'));
2770 }
2771
2772
2773
2774
2775 function testDBFieldExists() {
2776 $this->assertIdentical(TRUE, db_field_exists('node', 'nid'), t('Returns true for existent column.'));
2777 $this->assertIdentical(FALSE, db_field_exists('node', 'nosuchcolumn'), t('Returns false for nonexistent column.'));
2778 }
2779
2780
2781
2782
2783 function testDBIndexExists() {
2784 $this->assertIdentical(TRUE, db_index_exists('node', 'node_created'), t('Returns true for existent index.'));
2785 $this->assertIdentical(FALSE, db_index_exists('node', 'nosuchindex'), t('Returns false for nonexistent index.'));
2786 }
2787 }
2788
2789
2790
2791
2792 class DatabaseLoggingTestCase extends DatabaseTestCase {
2793
2794 public static function getInfo() {
2795 return array(
2796 'name' => 'Query logging',
2797 'description' => 'Test the query logging facility.',
2798 'group' => 'Database',
2799 );
2800 }
2801
2802
2803
2804
2805 function testEnableLogging() {
2806 $log = Database::startLog('testing');
2807
2808 db_query('SELECT name FROM {test} WHERE age > :age', array(':age' => 25))->fetchCol();
2809 db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'))->fetchCol();
2810
2811
2812 call_user_func_array('db_query', array('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo')))->fetchCol();
2813
2814 $queries = Database::getLog('testing', 'default');
2815
2816 $this->assertEqual(count($queries), 3, t('Correct number of queries recorded.'));
2817
2818 foreach ($queries as $query) {
2819 $this->assertEqual($query['caller']['function'], __FUNCTION__, t('Correct function in query log.'));
2820 }
2821 }
2822
2823
2824
2825
2826 function testEnableMultiLogging() {
2827 Database::startLog('testing1');
2828
2829 db_query('SELECT name FROM {test} WHERE age > :age', array(':age' => 25))->fetchCol();
2830
2831 Database::startLog('testing2');
2832
2833 db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'))->fetchCol();
2834
2835 $queries1 = Database::getLog('testing1');
2836 $queries2 = Database::getLog('testing2');
2837
2838 $this->assertEqual(count($queries1), 2, t('Correct number of queries recorded for log 1.'));
2839 $this->assertEqual(count($queries2), 1, t('Correct number of queries recorded for log 2.'));
2840 }
2841
2842
2843
2844
2845 function testEnableTargetLogging() {
2846
2847
2848 $connection_info = Database::getConnectionInfo('default');
2849 Database::addConnectionInfo('default', 'slave', $connection_info['default']);
2850
2851 Database::startLog('testing1');
2852
2853 db_query('SELECT name FROM {test} WHERE age > :age', array(':age' => 25))->fetchCol();
2854
2855 db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'), array('target' => 'slave'));
2856
2857 $queries1 = Database::getLog('testing1');
2858
2859 $this->assertEqual(count($queries1), 2, t('Recorded queries from all targets.'));
2860 $this->assertEqual($queries1[0]['target'], 'default', t('First query used default target.'));
2861 $this->assertEqual($queries1[1]['target'], 'slave', t('Second query used slave target.'));
2862 }
2863
2864
2865
2866
2867
2868
2869
2870
2871 function testEnableTargetLoggingNoTarget() {
2872 Database::startLog('testing1');
2873
2874 db_query('SELECT name FROM {test} WHERE age > :age', array(':age' => 25))->fetchCol();
2875
2876
2877
2878
2879
2880
2881 db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'), array('target' => 'fake'))->fetchCol();
2882
2883 $queries1 = Database::getLog('testing1');
2884
2885 $this->assertEqual(count($queries1), 2, t('Recorded queries from all targets.'));
2886 $this->assertEqual($queries1[0]['target'], 'default', t('First query used default target.'));
2887 $this->assertEqual($queries1[1]['target'], 'default', t('Second query used default target as fallback.'));
2888 }
2889
2890
2891
2892
2893 function testEnableMultiConnectionLogging() {
2894
2895
2896 $connection_info = Database::getConnectionInfo('default');
2897 Database::addConnectionInfo('test2', 'default', $connection_info['default']);
2898
2899 Database::startLog('testing1');
2900 Database::startLog('testing1', 'test2');
2901
2902 db_query('SELECT name FROM {test} WHERE age > :age', array(':age' => 25))->fetchCol();
2903
2904 $old_key = db_set_active('test2');
2905
2906 db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'), array('target' => 'slave'))->fetchCol();
2907
2908 db_set_active($old_key);
2909
2910 $queries1 = Database::getLog('testing1');
2911 $queries2 = Database::getLog('testing1', 'test2');
2912
2913 $this->assertEqual(count($queries1), 1, t('Correct number of queries recorded for first connection.'));
2914 $this->assertEqual(count($queries2), 1, t('Correct number of queries recorded for second connection.'));
2915 }
2916 }
2917
2918
2919
2920
2921 class DatabaseSerializeQueryTestCase extends DatabaseTestCase {
2922 public static function getInfo() {
2923 return array(
2924 'name' => 'Serialize query',
2925 'description' => 'Test serializing and unserializing a query.',
2926 'group' => 'Database',
2927 );
2928 }
2929
2930
2931
2932
2933 function testSerializeQuery() {
2934 $query = db_select('test');
2935 $query->addField('test', 'age');
2936 $query->condition('name', 'Ringo');
2937
2938
2939 $query = unserialize(serialize($query));
2940 $results = $query->execute()->fetchCol();
2941 $this->assertEqual($results[0], 28, t('Query properly executed after unserialization.'));
2942 }
2943 }
2944
2945
2946
2947
2948 class DatabaseRangeQueryTestCase extends DrupalWebTestCase {
2949 public static function getInfo() {
2950 return array(
2951 'name' => 'Range query test',
2952 'description' => 'Test the Range query functionality.',
2953 'group' => 'Database',
2954 );
2955 }
2956
2957 function setUp() {
2958 parent::setUp('database_test');
2959 }
2960
2961
2962
2963
2964 function testRangeQuery() {
2965
2966 $range_rows = db_query_range("SELECT name FROM {system} ORDER BY name", 2, 3)->fetchAll();
2967 $this->assertEqual(count($range_rows), 3, t('Range query work and return correct number of rows.'));
2968
2969
2970 $raw_rows = db_query('SELECT name FROM {system} ORDER BY name')->fetchAll();
2971 $raw_rows = array_slice($raw_rows, 2, 3);
2972 $this->assertEqual($range_rows, $raw_rows, t('Range query work and return target data.'));
2973 }
2974 }
2975
2976
2977
2978
2979 class DatabaseTemporaryQueryTestCase extends DrupalWebTestCase {
2980 public static function getInfo() {
2981 return array(
2982 'name' => 'Temporary query test',
2983 'description' => 'Test the temporary query functionality.',
2984 'group' => 'Database',
2985 );
2986 }
2987
2988 function setUp() {
2989 parent::setUp('database_test');
2990 }
2991
2992
2993
2994
2995 function countTableRows($table_name) {
2996 return db_select($table_name)->countQuery()->execute()->fetchField();
2997 }
2998
2999
3000
3001
3002 function testTemporaryQuery() {
3003 $this->drupalGet('database_test/db_query_temporary');
3004 $data = json_decode($this->drupalGetContent());
3005 if ($data) {
3006 $this->assertEqual($this->countTableRows("system"), $data->row_count, t('The temporary table contains the correct amount of rows.'));
3007 $this->assertFalse(db_table_exists($data->table_name), t('The temporary table is, indeed, temporary.'));
3008 }
3009 else {
3010 $this->fail(t("The creation of the temporary table failed."));
3011 }
3012
3013
3014 $table_name_system = db_query_temporary('SELECT status FROM {system}', array());
3015 $table_name_users = db_query_temporary('SELECT uid FROM {users}', array());
3016
3017 $this->assertEqual($this->countTableRows($table_name_system), $this->countTableRows("system"), t('A temporary table was created successfully in this request.'));
3018 $this->assertEqual($this->countTableRows($table_name_users), $this->countTableRows("users"), t('A second temporary table was created successfully in this request.'));
3019 }
3020 }
3021
3022
3023
3024
3025
3026
3027
3028
3029 class DatabaseBasicSyntaxTestCase extends DatabaseTestCase {
3030 public static function getInfo() {
3031 return array(
3032 'name' => 'Basic SQL syntax tests',
3033 'description' => 'Test SQL syntax interpretation.',
3034 'group' => 'Database',
3035 );
3036 }
3037
3038 function setUp() {
3039 parent::setUp('database_test');
3040 }
3041
3042
3043
3044
3045 function testBasicConcat() {
3046 $result = db_query('SELECT CONCAT(:a1, CONCAT(:a2, CONCAT(:a3, CONCAT(:a4, :a5))))', array(
3047 ':a1' => 'This',
3048 ':a2' => ' ',
3049 ':a3' => 'is',
3050 ':a4' => ' a ',
3051 ':a5' => 'test.',
3052 ));
3053 $this->assertIdentical($result->fetchField(), 'This is a test.', t('Basic CONCAT works.'));
3054 }
3055
3056
3057
3058
3059 function testFieldConcat() {
3060 $result = db_query('SELECT CONCAT(:a1, CONCAT(name, CONCAT(:a2, CONCAT(age, :a3)))) FROM {test} WHERE age = :age', array(
3061 ':a1' => 'The age of ',
3062 ':a2' => ' is ',
3063 ':a3' => '.',
3064 ':age' => 25,
3065 ));
3066 $this->assertIdentical($result->fetchField(), 'The age of John is 25.', t('Field CONCAT works.'));
3067 }
3068
3069
3070
3071
3072 function testLikeEscape() {
3073 db_insert('test')
3074 ->fields(array(
3075 'name' => 'Ring_',
3076 ))
3077 ->execute();
3078
3079
3080 $num_matches = db_select('test', 't')
3081 ->condition('name', 'Ring_', 'LIKE')
3082 ->countQuery()
3083 ->execute()
3084 ->fetchField();
3085 $this->assertIdentical($num_matches, '2', t('Found 2 records.'));
3086
3087 $num_matches = db_select('test', 't')
3088 ->condition('name', db_like('Ring_'), 'LIKE')
3089 ->countQuery()
3090 ->execute()
3091 ->fetchField();
3092 $this->assertIdentical($num_matches, '1', t('Found 1 record.'));
3093 }
3094
3095
3096
3097
3098 function testLikeBackslash() {
3099 db_insert('test')
3100 ->fields(array('name'))
3101 ->values(array(
3102 'name' => 'abcde\f',
3103 ))
3104 ->values(array(
3105 'name' => 'abc%\_',
3106 ))
3107 ->execute();
3108
3109
3110
3111 $num_matches = db_select('test', 't')
3112 ->condition('name', 'abc%\\\\_', 'LIKE')
3113 ->countQuery()
3114 ->execute()
3115 ->fetchField();
3116 $this->assertIdentical($num_matches, '2', t('Found 2 records.'));
3117
3118 $num_matches = db_select('test', 't')
3119 ->condition('name', db_like('abc%\_'), 'LIKE')
3120 ->countQuery()
3121 ->execute()
3122 ->fetchField();
3123 $this->assertIdentical($num_matches, '1', t('Found 1 record.'));
3124 }
3125 }
3126
3127
3128
3129
3130 class DatabaseCaseSensitivityTestCase extends DatabaseTestCase {
3131 public static function getInfo() {
3132 return array(
3133 'name' => 'Case sensitivity',
3134 'description' => 'Test handling case sensitive collation.',
3135 'group' => 'Database',
3136 );
3137 }
3138
3139
3140
3141
3142 function testCaseSensitiveInsert() {
3143 $num_records_before = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
3144
3145 $john = db_insert('test')
3146 ->fields(array(
3147 'name' => 'john', // <- A record already exists with name 'John'.
3148 'age' => 2,
3149 'job' => 'Baby',
3150 ))
3151 ->execute();
3152
3153 $num_records_after = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
3154 $this->assertIdentical($num_records_before + 1, (int) $num_records_after, t('Record inserts correctly.'));
3155 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'john'))->fetchField();
3156 $this->assertIdentical($saved_age, '2', t('Can retrieve after inserting.'));
3157 }
3158 }
3159
3160
3161
3162
3163 class DatabaseInvalidDataTestCase extends DatabaseTestCase {
3164 public static function getInfo() {
3165 return array(
3166 'name' => 'Invalid data',
3167 'description' => 'Test handling of some invalid data.',
3168 'group' => 'Database',
3169 );
3170 }
3171
3172 function setUp() {
3173 parent::setUp('database_test');
3174 }
3175
3176
3177
3178
3179 function testInsertDuplicateData() {
3180
3181 try {
3182 db_insert('test')
3183 ->fields(array('name', 'age', 'job'))
3184 ->values(array(
3185 'name' => 'Elvis',
3186 'age' => 63,
3187 'job' => 'Singer',
3188 ))->values(array(
3189 'name' => 'John', // <-- Duplicate value on unique field.
3190 'age' => 17,
3191 'job' => 'Consultant',
3192 ))
3193 ->values(array(
3194 'name' => 'Frank',
3195 'age' => 75,
3196 'job' => 'Singer',
3197 ))
3198 ->execute();
3199 $this->fail(t('Insert succeedded when it should not have.'));
3200 }
3201 catch (Exception $e) {
3202
3203 $name = db_query('SELECT name FROM {test} WHERE age = :age', array(':age' => 63))->fetchField();
3204
3205 if ($name == 'Elvis') {
3206 if (!Database::getConnection()->supportsTransactions()) {
3207
3208
3209
3210
3211 $this->pass(t("The whole transaction has not been rolled-back when a duplicate key insert occurs, this is expected because the database doesn't support transactions"));
3212 }
3213 else {
3214 $this->fail(t('The whole transaction is rolled back when a duplicate key insert occurs.'));
3215 }
3216 }
3217 else {
3218 $this->pass(t('The whole transaction is rolled back when a duplicate key insert occurs.'));
3219 }
3220
3221
3222 $record = db_select('test')
3223 ->fields('test', array('name', 'age'))
3224 ->condition('age', array(17, 75), 'IN')
3225 ->execute()->fetchObject();
3226
3227 $this->assertFalse($record, t('The rest of the insert aborted as expected.'));
3228 }
3229 }
3230
3231 }
3232
3233
3234
3235
3236 class DatabaseQueryTestCase extends DatabaseTestCase {
3237 public static function getInfo() {
3238 return array(
3239 'name' => 'Custom query syntax tests',
3240 'description' => 'Test Drupal\'s extended prepared statement syntax..',
3241 'group' => 'Database',
3242 );
3243 }
3244
3245 function setUp() {
3246 parent::setUp('database_test');
3247 }
3248
3249
3250
3251
3252 function testArraySubstitution() {
3253 $names = db_query('SELECT name FROM {test} WHERE age IN (:ages) ORDER BY age', array(':ages' => array(25, 26, 27)))->fetchAll();
3254
3255 $this->assertEqual(count($names), 3, t('Correct number of names returned'));
3256 }
3257 }
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279 class DatabaseTransactionTestCase extends DatabaseTestCase {
3280
3281 public static function getInfo() {
3282 return array(
3283 'name' => 'Transaction tests',
3284 'description' => 'Test the transaction abstraction system.',
3285 'group' => 'Database',
3286 );
3287 }
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310 protected function transactionOuterLayer($suffix, $rollback = FALSE, $ddl_statement = FALSE) {
3311 $connection = Database::getConnection();
3312 $depth = $connection->transactionDepth();
3313 $txn = db_transaction();
3314
3315
3316 db_insert('test')
3317 ->fields(array(
3318 'name' => 'David' . $suffix,
3319 'age' => '24',
3320 ))
3321 ->execute();
3322
3323 $this->assertTrue($connection->inTransaction(), t('In transaction before calling nested transaction.'));
3324
3325
3326
3327 $this->transactionInnerLayer($suffix, $rollback, $ddl_statement);
3328
3329 $this->assertTrue($connection->inTransaction(), t('In transaction after calling nested transaction.'));
3330
3331 if ($rollback) {
3332
3333
3334 $txn->rollback();
3335 $this->assertTrue(($connection->transactionDepth() == $depth), t('Transaction has rolled back to the last savepoint after calling rollback().'));
3336 }
3337 }
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350 protected function transactionInnerLayer($suffix, $rollback = FALSE, $ddl_statement = FALSE) {
3351 $connection = Database::getConnection();
3352
3353 $depth = $connection->transactionDepth();
3354
3355
3356
3357
3358 $txn = db_transaction();
3359
3360 $depth2 = $connection->transactionDepth();
3361 $this->assertTrue($depth < $depth2, t('Transaction depth is has increased with new transaction.'));
3362
3363
3364 db_insert('test')
3365 ->fields(array(
3366 'name' => 'Daniel' . $suffix,
3367 'age' => '19',
3368 ))
3369 ->execute();
3370
3371 $this->assertTrue($connection->inTransaction(), t('In transaction inside nested transaction.'));
3372
3373 if ($ddl_statement) {
3374 $table = array(
3375 'fields' => array(
3376 'id' => array(
3377 'type' => 'serial',
3378 'unsigned' => TRUE,
3379 'not null' => TRUE,
3380 ),
3381 ),
3382 'primary key' => array('id'),
3383 );
3384 db_create_table('database_test_1', $table);
3385
3386 $this->assertTrue($connection->inTransaction(), t('In transaction inside nested transaction.'));
3387 }
3388
3389 if ($rollback) {
3390
3391
3392 $txn->rollback();
3393 $this->assertTrue(($connection->transactionDepth() == $depth), t('Transaction has rolled back to the last savepoint after calling rollback().'));
3394 }
3395 }
3396
3397
3398
3399
3400
3401
3402 function testTransactionRollBackSupported() {
3403
3404 if (!Database::getConnection()->supportsTransactions()) {
3405 return;
3406 }
3407 try {
3408
3409 $this->transactionOuterLayer('B', TRUE);
3410
3411
3412
3413 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'DavidB'))->fetchField();
3414 $this->assertNotIdentical($saved_age, '24', t('Cannot retrieve DavidB row after commit.'));
3415 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'DanielB'))->fetchField();
3416 $this->assertNotIdentical($saved_age, '19', t('Cannot retrieve DanielB row after commit.'));
3417 }
3418 catch (Exception $e) {
3419 $this->fail($e->getMessage());
3420 }
3421 }
3422
3423
3424
3425
3426
3427
3428 function testTransactionRollBackNotSupported() {
3429
3430 if (Database::getConnection()->supportsTransactions()) {
3431 return;
3432 }
3433 try {
3434
3435 $this->transactionOuterLayer('B', TRUE);
3436
3437
3438
3439 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'DavidB'))->fetchField();
3440 $this->assertIdentical($saved_age, '24', t('DavidB not rolled back, since transactions are not supported.'));
3441 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'DanielB'))->fetchField();
3442 $this->assertIdentical($saved_age, '19', t('DanielB not rolled back, since transactions are not supported.'));
3443 }
3444 catch (Exception $e) {
3445 $this->fail($e->getMessage());
3446 }
3447 }
3448
3449
3450
3451
3452
3453
3454
3455 function testCommittedTransaction() {
3456 try {
3457
3458 $this->transactionOuterLayer('A');
3459
3460
3461 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'DavidA'))->fetchField();
3462 $this->assertIdentical($saved_age, '24', t('Can retrieve DavidA row after commit.'));
3463 $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'DanielA'))->fetchField();
3464 $this->assertIdentical($saved_age, '19', t('Can retrieve DanielA row after commit.'));
3465 }
3466 catch (Exception $e) {
3467 $this->fail($e->getMessage());
3468 }
3469 }
3470
3471
3472
3473
3474 function testTransactionWithDdlStatement() {
3475
3476 $transaction = db_transaction();
3477 $this->insertRow('row');
3478 $this->executeDDLStatement();
3479 unset($transaction);
3480 $this->assertRowPresent('row');
3481
3482
3483 $this->cleanUp();
3484 $transaction = db_transaction();
3485 $this->executeDDLStatement();
3486 $this->insertRow('row');
3487 unset($transaction);
3488 $this->assertRowPresent('row');
3489
3490
3491 $this->cleanUp();
3492 $transaction = db_transaction();
3493 $transaction2 = db_transaction();
3494 $this->executeDDLStatement();
3495 unset($transaction2);
3496 $transaction3 = db_transaction();
3497 $this->insertRow('row');
3498 unset($transaction3);
3499 unset($transaction);
3500 $this->assertRowPresent('row');
3501
3502
3503 $this->cleanUp();
3504 $transaction = db_transaction();
3505 $transaction2 = db_transaction();
3506 $this->executeDDLStatement();
3507 unset($transaction2);
3508 $transaction3 = db_transaction();
3509 $this->insertRow('row');
3510 $transaction3->rollback();
3511 unset($transaction3);
3512 unset($transaction);
3513 $this->assertRowAbsent('row');
3514
3515
3516 if (Database::getConnection()->supportsTransactionalDDL()) {
3517
3518
3519 $this->cleanUp();
3520 $transaction = db_transaction();
3521 $this->insertRow('row');
3522 $this->executeDDLStatement();
3523 $transaction->rollback();
3524 unset($transaction);
3525 $this->assertRowAbsent('row');
3526
3527
3528 $this->cleanUp();
3529 $transaction = db_transaction();
3530 $transaction2 = db_transaction();
3531 $this->executeDDLStatement();
3532 unset($transaction2);
3533 $transaction3 = db_transaction();
3534 $this->insertRow('row');
3535 unset($transaction3);
3536 $transaction->rollback();
3537 unset($transaction);
3538 $this->assertRowAbsent('row');
3539 }
3540 else {
3541
3542
3543 $this->cleanUp();
3544 $transaction = db_transaction();
3545 $this->insertRow('row');
3546 $this->executeDDLStatement();
3547
3548 try {
3549 $transaction->rollback();
3550 unset($transaction);
3551
3552
3553
3554 }
3555 catch (DatabaseTransactionNoActiveException $e) {
3556 $this->pass(t('Rolling back a transaction containing DDL should fail.'));
3557 }
3558 $this->assertRowPresent('row');
3559 }
3560 }
3561
3562
3563
3564
3565 protected function insertRow($name) {
3566 db_insert('test')
3567 ->fields(array(
3568 'name' => $name,
3569 ))
3570 ->execute();
3571 }
3572
3573
3574
3575
3576 protected function executeDDLStatement() {
3577 static $count = 0;
3578 $table = array(
3579 'fields' => array(
3580 'id' => array(
3581 'type' => 'serial',
3582 'unsigned' => TRUE,
3583 'not null' => TRUE,
3584 ),
3585 ),
3586 'primary key' => array('id'),
3587 );
3588 db_create_table('database_test_' . ++$count, $table);
3589 }
3590
3591
3592
3593
3594 protected function cleanUp() {
3595 db_truncate('test')
3596 ->execute();
3597 }
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607 function assertRowPresent($name, $message = NULL) {
3608 if (!isset($message)) {
3609 $message = t('Row %name is present.', array('%name' => $name));
3610 }
3611 $present = (boolean) db_query('SELECT 1 FROM {test} WHERE name = :name', array(':name' => $name))->fetchField();
3612 return $this->assertTrue($present, $message);
3613 }
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623 function assertRowAbsent($name, $message = NULL) {
3624 if (!isset($message)) {
3625 $message = t('Row %name is absent.', array('%name' => $name));
3626 }
3627 $present = (boolean) db_query('SELECT 1 FROM {test} WHERE name = :name', array(':name' => $name))->fetchField();
3628 return $this->assertFalse($present, $message);
3629 }
3630
3631
3632
3633
3634 function testTransactionStacking() {
3635
3636 if (!Database::getConnection()->supportsTransactions()) {
3637 return;
3638 }
3639
3640 $database = Database::getConnection();
3641
3642
3643 $transaction = db_transaction();
3644 $this->insertRow('outer');
3645 $transaction2 = db_transaction();
3646 $this->insertRow('inner');
3647
3648 unset($transaction2);
3649 $this->assertTrue($database->inTransaction(), t('Still in a transaction after popping the inner transaction'));
3650
3651 unset($transaction);
3652 $this->assertFalse($database->inTransaction(), t('Transaction closed after popping the outer transaction'));
3653 $this->assertRowPresent('outer');
3654 $this->assertRowPresent('inner');
3655
3656
3657 $this->cleanUp();
3658 $transaction = db_transaction();
3659 $this->insertRow('outer');
3660 $transaction2 = db_transaction();
3661 $this->insertRow('inner');
3662
3663 unset($transaction);
3664 $this->insertRow('inner-after-outer-commit');
3665 $this->assertTrue($database->inTransaction(), t('Still in a transaction after popping the outer transaction'));
3666
3667 unset($transaction2);
3668 $this->assertFalse($database->inTransaction(), t('Transaction closed after popping the inner transaction'));
3669 $this->assertRowPresent('outer');
3670 $this->assertRowPresent('inner');
3671 $this->assertRowPresent('inner-after-outer-commit');
3672
3673
3674 $this->cleanUp();
3675 $transaction = db_transaction();
3676 $this->insertRow('outer');
3677 $transaction2 = db_transaction();
3678 $this->insertRow('inner');
3679
3680 $transaction2->rollback();
3681 unset($transaction2);
3682 $this->assertTrue($database->inTransaction(), t('Still in a transaction after popping the outer transaction'));
3683
3684 $this->insertRow('outer-after-inner-rollback');
3685 unset($transaction);
3686 $this->assertFalse($database->inTransaction(), t('Transaction closed after popping the inner transaction'));
3687 $this->assertRowPresent('outer');
3688 $this->assertRowAbsent('inner');
3689 $this->assertRowPresent('outer-after-inner-rollback');
3690
3691
3692 $this->cleanUp();
3693 $transaction = db_transaction();
3694 $this->insertRow('outer');
3695 $transaction2 = db_transaction();
3696 $this->insertRow('inner');
3697
3698 unset($transaction);
3699 $this->assertTrue($database->inTransaction(), t('Still in a transaction after popping the outer transaction'));
3700
3701 $transaction2->rollback();
3702 unset($transaction2);
3703 $this->assertFalse($database->inTransaction(), t('Transaction closed after popping the inner transaction'));
3704 $this->assertRowPresent('outer');
3705 $this->assertRowAbsent('inner');
3706
3707
3708
3709
3710 $this->cleanUp();
3711 $transaction = db_transaction();
3712 $this->insertRow('outer');
3713 $transaction2 = db_transaction();
3714 $this->insertRow('inner');
3715 $transaction3 = db_transaction();
3716 $this->insertRow('inner2');
3717
3718 try {
3719 $transaction->rollback();
3720 unset($transaction);
3721 $this->fail(t('Rolling back the outer transaction while the inner transaction is active resulted in an exception.'));
3722 }
3723 catch (DatabaseTransactionOutOfOrderException $e) {
3724 $this->pass(t('Rolling back the outer transaction while the inner transaction is active resulted in an exception.'));
3725 }
3726 $this->assertFalse($database->inTransaction(), t('No more in a transaction after rolling back the outer transaction'));
3727
3728 unset($transaction3);
3729 $this->pass(t('Trying to commit an inner transaction resulted in an exception.'));
3730
3731 try {
3732 $transaction->rollback();
3733 unset($transaction2);
3734 $this->fail(t('Trying to commit an inner transaction resulted in an exception.'));
3735 }
3736 catch (DatabaseTransactionNoActiveException $e) {
3737 $this->pass(t('Trying to commit an inner transaction resulted in an exception.'));
3738 }
3739 $this->assertRowAbsent('outer');
3740 $this->assertRowAbsent('inner');
3741 $this->assertRowAbsent('inner2');
3742 }
3743 }
3744
3745
3746
3747
3748
3749 class DatabaseNextIdCase extends DrupalWebTestCase {
3750 public static function getInfo() {
3751 return array(
3752 'name' => 'Sequences API',
3753 'description' => 'Test the secondary sequences API.',
3754 'group' => 'Database',
3755 );
3756 }
3757
3758
3759
3760
3761 function testDbNextId() {
3762 $first = db_next_id();
3763 $second = db_next_id();
3764
3765
3766
3767 $this->assertEqual($first + 1, $second, t('The second call from a sequence provides a number increased by one.'));
3768 $result = db_next_id(1000);
3769 $this->assertEqual($result, 1001, t('Sequence provides a larger number than the existing ID.'));
3770 }
3771 }
3772
3773
3774
3775
3776 class DatabaseEmptyStatementTestCase extends DrupalWebTestCase {
3777 public static function getInfo() {
3778 return array(
3779 'name' => 'Empty statement',
3780 'description' => 'Test the empty pseudo-statement class.',
3781 'group' => 'Database',
3782 );
3783 }
3784
3785
3786
3787
3788 function testEmpty() {
3789 $result = new DatabaseStatementEmpty();
3790
3791 $this->assertTrue($result instanceof DatabaseStatementInterface, t('Class implements expected interface'));
3792 $this->assertNull($result->fetchObject(), t('Null result returned.'));
3793 }
3794
3795
3796
3797
3798 function testEmptyIteration() {
3799 $result = new DatabaseStatementEmpty();
3800
3801 foreach ($result as $record) {
3802 $this->fail(t('Iterating empty result set should not iterate.'));
3803 return;
3804 }
3805
3806 $this->pass(t('Iterating empty result set skipped iteration.'));
3807 }
3808
3809
3810
3811
3812 function testEmptyFetchAll() {
3813 $result = new DatabaseStatementEmpty();
3814
3815 $this->assertEqual($result->fetchAll(), array(), t('Empty array returned from empty result set.'));
3816 }
3817 }