統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Test / Case / Model / Datasource / DboSourceTest.php @ 635eef61

履歴 | 表示 | アノテート | ダウンロード (54.392 KB)

1 635eef61 spyder1211
<?php
2
/**
3
 * DboSourceTest file
4
 *
5
 * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
6
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
7
 *
8
 * Licensed under The MIT License
9
 * For full copyright and license information, please see the LICENSE.txt
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
13
 * @link          http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
14
 * @package       Cake.Test.Case.Model.Datasource
15
 * @since         CakePHP(tm) v 1.2.0.4206
16
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
17
 */
18
19
App::uses('Model', 'Model');
20
App::uses('AppModel', 'Model');
21
App::uses('DataSource', 'Model/Datasource');
22
App::uses('DboSource', 'Model/Datasource');
23
App::uses('DboTestSource', 'Model/Datasource');
24
App::uses('DboSecondTestSource', 'Model/Datasource');
25
App::uses('MockDataSource', 'Model/Datasource');
26
27
require_once dirname(dirname(__FILE__)) . DS . 'models.php';
28
29
/**
30
 * Class MockPDO
31
 *
32
 * @package       Cake.Test.Case.Model.Datasource
33
 */
34
class MockPDO extends PDO {
35
36
/**
37
 * Constructor.
38
 */
39
        public function __construct() {
40
        }
41
42
}
43
44
/**
45
 * Class MockDataSource
46
 *
47
 * @package       Cake.Test.Case.Model.Datasource
48
 */
49
class MockDataSource extends DataSource {
50
}
51
52
/**
53
 * Class DboTestSource
54
 *
55
 * @package       Cake.Test.Case.Model.Datasource
56
 */
57
class DboTestSource extends DboSource {
58
59
        public $nestedSupport = false;
60
61
        public function connect($config = array()) {
62
                $this->connected = true;
63
        }
64
65
        public function mergeAssociation(&$data, &$merge, $association, $type, $selfJoin = false) {
66
                return parent::_mergeAssociation($data, $merge, $association, $type, $selfJoin);
67
        }
68
69
        public function setConfig($config = array()) {
70
                $this->config = $config;
71
        }
72
73
        public function setConnection($conn) {
74
                $this->_connection = $conn;
75
        }
76
77
        public function nestedTransactionSupported() {
78
                return $this->useNestedTransactions && $this->nestedSupport;
79
        }
80
81
}
82
83
/**
84
 * Class DboSecondTestSource
85
 *
86
 * @package       Cake.Test.Case.Model.Datasource
87
 */
88
class DboSecondTestSource extends DboSource {
89
90
        public $startQuote = '_';
91
92
        public $endQuote = '_';
93
94
        public function connect($config = array()) {
95
                $this->connected = true;
96
        }
97
98
        public function mergeAssociation(&$data, &$merge, $association, $type, $selfJoin = false) {
99
                return parent::_mergeAssociation($data, $merge, $association, $type, $selfJoin);
100
        }
101
102
        public function setConfig($config = array()) {
103
                $this->config = $config;
104
        }
105
106
        public function setConnection($conn) {
107
                $this->_connection = $conn;
108
        }
109
110
}
111
112
/**
113
 * DboSourceTest class
114
 *
115
 * @package       Cake.Test.Case.Model.Datasource
116
 */
117
class DboSourceTest extends CakeTestCase {
118
119
/**
120
 * autoFixtures property
121
 *
122
 * @var bool
123
 */
124
        public $autoFixtures = false;
125
126
/**
127
 * fixtures property
128
 *
129
 * @var array
130
 */
131
        public $fixtures = array(
132
                'core.apple', 'core.article', 'core.articles_tag', 'core.attachment', 'core.comment',
133
                'core.sample', 'core.tag', 'core.user', 'core.post', 'core.author', 'core.data_test'
134
        );
135
136
/**
137
 * setUp method
138
 *
139
 * @return void
140
 */
141
        public function setUp() {
142
                parent::setUp();
143
144
                $this->testDb = new DboTestSource();
145
                $this->testDb->cacheSources = false;
146
                $this->testDb->startQuote = '`';
147
                $this->testDb->endQuote = '`';
148
149
                $this->Model = new TestModel();
150
        }
151
152
/**
153
 * tearDown method
154
 *
155
 * @return void
156
 */
157
        public function tearDown() {
158
                parent::tearDown();
159
                unset($this->Model);
160
        }
161
162
/**
163
 * test that booleans and null make logical condition strings.
164
 *
165
 * @return void
166
 */
167
        public function testBooleanNullConditionsParsing() {
168
                $result = $this->testDb->conditions(true);
169
                $this->assertEquals(' WHERE 1 = 1', $result, 'true conditions failed %s');
170
171
                $result = $this->testDb->conditions(false);
172
                $this->assertEquals(' WHERE 0 = 1', $result, 'false conditions failed %s');
173
174
                $result = $this->testDb->conditions(null);
175
                $this->assertEquals(' WHERE 1 = 1', $result, 'null conditions failed %s');
176
177
                $result = $this->testDb->conditions(array());
178
                $this->assertEquals(' WHERE 1 = 1', $result, 'array() conditions failed %s');
179
180
                $result = $this->testDb->conditions('');
181
                $this->assertEquals(' WHERE 1 = 1', $result, '"" conditions failed %s');
182
183
                $result = $this->testDb->conditions(' ', '"  " conditions failed %s');
184
                $this->assertEquals(' WHERE 1 = 1', $result);
185
        }
186
187
/**
188
 * test that booleans work on empty set.
189
 *
190
 * @return void
191
 */
192
        public function testBooleanEmptyConditionsParsing() {
193
                $result = $this->testDb->conditions(array('OR' => array()));
194
                $this->assertEquals(' WHERE  1 = 1', $result, 'empty conditions failed');
195
196
                $result = $this->testDb->conditions(array('OR' => array('OR' => array())));
197
                $this->assertEquals(' WHERE  1 = 1', $result, 'nested empty conditions failed');
198
        }
199
200
/**
201
 * test that order() will accept objects made from DboSource::expression
202
 *
203
 * @return void
204
 */
205
        public function testOrderWithExpression() {
206
                $expression = $this->testDb->expression("CASE Sample.id WHEN 1 THEN 'Id One' ELSE 'Other Id' END AS case_col");
207
                $result = $this->testDb->order($expression);
208
                $expected = " ORDER BY CASE Sample.id WHEN 1 THEN 'Id One' ELSE 'Other Id' END AS case_col";
209
                $this->assertEquals($expected, $result);
210
        }
211
212
/**
213
 * testMergeAssociations method
214
 *
215
 * @return void
216
 */
217
        public function testMergeAssociations() {
218
                $data = array('Article2' => array(
219
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article',
220
                                'body' => 'First Article Body', 'published' => 'Y',
221
                                'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
222
                ));
223
                $merge = array('Topic' => array(array(
224
                        'id' => '1', 'topic' => 'Topic', 'created' => '2007-03-17 01:16:23',
225
                        'updated' => '2007-03-17 01:18:31'
226
                )));
227
                $expected = array(
228
                        'Article2' => array(
229
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article',
230
                                'body' => 'First Article Body', 'published' => 'Y',
231
                                'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
232
                        ),
233
                        'Topic' => array(
234
                                'id' => '1', 'topic' => 'Topic', 'created' => '2007-03-17 01:16:23',
235
                                'updated' => '2007-03-17 01:18:31'
236
                        )
237
                );
238
                $this->testDb->mergeAssociation($data, $merge, 'Topic', 'hasOne');
239
                $this->assertEquals($expected, $data);
240
241
                $data = array('Article2' => array(
242
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article',
243
                                'body' => 'First Article Body', 'published' => 'Y',
244
                                'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
245
                ));
246
                $merge = array('User2' => array(array(
247
                        'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
248
                        'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
249
                )));
250
251
                $expected = array(
252
                        'Article2' => array(
253
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article',
254
                                'body' => 'First Article Body', 'published' => 'Y',
255
                                'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
256
                        ),
257
                        'User2' => array(
258
                                'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
259
                        )
260
                );
261
                $this->testDb->mergeAssociation($data, $merge, 'User2', 'belongsTo');
262
                $this->assertEquals($expected, $data);
263
264
                $data = array(
265
                        'Article2' => array(
266
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
267
                        )
268
                );
269
                $merge = array(array('Comment' => false));
270
                $expected = array(
271
                        'Article2' => array(
272
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
273
                        ),
274
                        'Comment' => array()
275
                );
276
                $this->testDb->mergeAssociation($data, $merge, 'Comment', 'hasMany');
277
                $this->assertEquals($expected, $data);
278
279
                $data = array(
280
                        'Article' => array(
281
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
282
                        )
283
                );
284
                $merge = array(
285
                        array(
286
                                'Comment' => array(
287
                                        'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
288
                                )
289
                        ),
290
                        array(
291
                                'Comment' => array(
292
                                        'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
293
                                )
294
                        )
295
                );
296
                $expected = array(
297
                        'Article' => array(
298
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
299
                        ),
300
                        'Comment' => array(
301
                                array(
302
                                        'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
303
                                ),
304
                                array(
305
                                        'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
306
                                )
307
                        )
308
                );
309
                $this->testDb->mergeAssociation($data, $merge, 'Comment', 'hasMany');
310
                $this->assertEquals($expected, $data);
311
312
                $data = array(
313
                        'Article' => array(
314
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
315
                        )
316
                );
317
                $merge = array(
318
                        array(
319
                                'Comment' => array(
320
                                        'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
321
                                ),
322
                                'User2' => array(
323
                                        'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
324
                                )
325
                        ),
326
                        array(
327
                                'Comment' => array(
328
                                        'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
329
                                ),
330
                                'User2' => array(
331
                                        'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
332
                                )
333
                        )
334
                );
335
                $expected = array(
336
                        'Article' => array(
337
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
338
                        ),
339
                        'Comment' => array(
340
                                array(
341
                                        'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31',
342
                                        'User2' => array(
343
                                                'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
344
                                        )
345
                                ),
346
                                array(
347
                                        'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31',
348
                                        'User2' => array(
349
                                                'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
350
                                        )
351
                                )
352
                        )
353
                );
354
                $this->testDb->mergeAssociation($data, $merge, 'Comment', 'hasMany');
355
                $this->assertEquals($expected, $data);
356
357
                $data = array(
358
                        'Article' => array(
359
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
360
                        )
361
                );
362
                $merge = array(
363
                        array(
364
                                'Comment' => array(
365
                                        'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
366
                                ),
367
                                'User2' => array(
368
                                        'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
369
                                ),
370
                                'Tag' => array(
371
                                        array('id' => 1, 'tag' => 'Tag 1'),
372
                                        array('id' => 2, 'tag' => 'Tag 2')
373
                                )
374
                        ),
375
                        array(
376
                                'Comment' => array(
377
                                        'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
378
                                ),
379
                                'User2' => array(
380
                                        'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
381
                                ),
382
                                'Tag' => array()
383
                        )
384
                );
385
                $expected = array(
386
                        'Article' => array(
387
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
388
                        ),
389
                        'Comment' => array(
390
                                array(
391
                                        'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31',
392
                                        'User2' => array(
393
                                                'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
394
                                        ),
395
                                        'Tag' => array(
396
                                                array('id' => 1, 'tag' => 'Tag 1'),
397
                                                array('id' => 2, 'tag' => 'Tag 2')
398
                                        )
399
                                ),
400
                                array(
401
                                        'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31',
402
                                        'User2' => array(
403
                                                'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
404
                                        ),
405
                                        'Tag' => array()
406
                                )
407
                        )
408
                );
409
                $this->testDb->mergeAssociation($data, $merge, 'Comment', 'hasMany');
410
                $this->assertEquals($expected, $data);
411
412
                $data = array(
413
                        'Article' => array(
414
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
415
                        )
416
                );
417
                $merge = array(
418
                        array(
419
                                'Tag' => array(
420
                                        'id' => '1', 'tag' => 'Tag 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
421
                                )
422
                        ),
423
                        array(
424
                                'Tag' => array(
425
                                        'id' => '2', 'tag' => 'Tag 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
426
                                )
427
                        ),
428
                        array(
429
                                'Tag' => array(
430
                                        'id' => '3', 'tag' => 'Tag 3', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
431
                                )
432
                        )
433
                );
434
                $expected = array(
435
                        'Article' => array(
436
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
437
                        ),
438
                        'Tag' => array(
439
                                array(
440
                                        'id' => '1', 'tag' => 'Tag 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
441
                                ),
442
                                array(
443
                                        'id' => '2', 'tag' => 'Tag 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
444
                                ),
445
                                array(
446
                                        'id' => '3', 'tag' => 'Tag 3', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
447
                                )
448
                        )
449
                );
450
                $this->testDb->mergeAssociation($data, $merge, 'Tag', 'hasAndBelongsToMany');
451
                $this->assertEquals($expected, $data);
452
453
                $data = array(
454
                        'Article' => array(
455
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
456
                        )
457
                );
458
                $merge = array(
459
                        array(
460
                                'Tag' => array(
461
                                        'id' => '1', 'tag' => 'Tag 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
462
                                )
463
                        ),
464
                        array(
465
                                'Tag' => array(
466
                                        'id' => '2', 'tag' => 'Tag 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
467
                                )
468
                        ),
469
                        array(
470
                                'Tag' => array(
471
                                        'id' => '3', 'tag' => 'Tag 3', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'
472
                                )
473
                        )
474
                );
475
                $expected = array(
476
                        'Article' => array(
477
                                'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'
478
                        ),
479
                        'Tag' => array('id' => '1', 'tag' => 'Tag 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31')
480
                );
481
                $this->testDb->mergeAssociation($data, $merge, 'Tag', 'hasOne');
482
                $this->assertEquals($expected, $data);
483
        }
484
485
/**
486
 * testMagicMethodQuerying method
487
 *
488
 * @return void
489
 */
490
        public function testMagicMethodQuerying() {
491
                $result = $this->db->query('findByFieldName', array('value'), $this->Model);
492
                $expected = array('first', array(
493
                        'conditions' => array('TestModel.field_name' => 'value'),
494
                        'fields' => null, 'order' => null, 'recursive' => null
495
                ));
496
                $this->assertEquals($expected, $result);
497
498
                $result = $this->db->query('findByFindBy', array('value'), $this->Model);
499
                $expected = array('first', array(
500
                        'conditions' => array('TestModel.find_by' => 'value'),
501
                        'fields' => null, 'order' => null, 'recursive' => null
502
                ));
503
                $this->assertEquals($expected, $result);
504
505
                $result = $this->db->query('findAllByFieldName', array('value'), $this->Model);
506
                $expected = array('all', array(
507
                        'conditions' => array('TestModel.field_name' => 'value'),
508
                        'fields' => null, 'order' => null, 'limit' => null,
509
                        'page' => null, 'recursive' => null
510
                ));
511
                $this->assertEquals($expected, $result);
512
513
                $result = $this->db->query('findAllById', array('a'), $this->Model);
514
                $expected = array('all', array(
515
                        'conditions' => array('TestModel.id' => 'a'),
516
                        'fields' => null, 'order' => null, 'limit' => null,
517
                        'page' => null, 'recursive' => null
518
                ));
519
                $this->assertEquals($expected, $result);
520
521
                $result = $this->db->query('findByFieldName', array(array('value1', 'value2', 'value3')), $this->Model);
522
                $expected = array('first', array(
523
                        'conditions' => array('TestModel.field_name' => array('value1', 'value2', 'value3')),
524
                        'fields' => null, 'order' => null, 'recursive' => null
525
                ));
526
                $this->assertEquals($expected, $result);
527
528
                $result = $this->db->query('findByFieldName', array(null), $this->Model);
529
                $expected = array('first', array(
530
                        'conditions' => array('TestModel.field_name' => null),
531
                        'fields' => null, 'order' => null, 'recursive' => null
532
                ));
533
                $this->assertEquals($expected, $result);
534
535
                $result = $this->db->query('findByFieldName', array('= a'), $this->Model);
536
                $expected = array('first', array(
537
                        'conditions' => array('TestModel.field_name' => '= a'),
538
                        'fields' => null, 'order' => null, 'recursive' => null
539
                ));
540
                $this->assertEquals($expected, $result);
541
542
                $result = $this->db->query('findByFieldName', array(), $this->Model);
543
                $expected = false;
544
                $this->assertEquals($expected, $result);
545
        }
546
547
/**
548
 * @expectedException PDOException
549
 * @return void
550
 */
551
        public function testDirectCallThrowsException() {
552
                $this->db->query('directCall', array(), $this->Model);
553
        }
554
555
/**
556
 * testValue method
557
 *
558
 * @return void
559
 */
560
        public function testValue() {
561
                if ($this->db instanceof Sqlserver) {
562
                        $this->markTestSkipped('Cannot run this test with SqlServer');
563
                }
564
                $result = $this->db->value('{$__cakeForeignKey__$}');
565
                $this->assertEquals('{$__cakeForeignKey__$}', $result);
566
567
                $result = $this->db->value(array('first', 2, 'third'));
568
                $expected = array('\'first\'', 2, '\'third\'');
569
                $this->assertEquals($expected, $result);
570
        }
571
572
/**
573
 * Tests if the connection can be re-established and that the new (optional) config is set.
574
 *
575
 * @return void
576
 */
577
        public function testReconnect() {
578
                $this->testDb->reconnect(array('prefix' => 'foo'));
579
                $this->assertTrue($this->testDb->connected);
580
                $this->assertEquals('foo', $this->testDb->config['prefix']);
581
        }
582
583
/**
584
 * testName method
585
 *
586
 * @return void
587
 */
588
        public function testName() {
589
                $result = $this->testDb->name('name');
590
                $expected = '`name`';
591
                $this->assertEquals($expected, $result);
592
593
                $result = $this->testDb->name(array('name', 'Model.*'));
594
                $expected = array('`name`', '`Model`.*');
595
                $this->assertEquals($expected, $result);
596
597
                $result = $this->testDb->name('MTD()');
598
                $expected = 'MTD()';
599
                $this->assertEquals($expected, $result);
600
601
                $result = $this->testDb->name('(sm)');
602
                $expected = '(sm)';
603
                $this->assertEquals($expected, $result);
604
605
                $result = $this->testDb->name('name AS x');
606
                $expected = '`name` AS `x`';
607
                $this->assertEquals($expected, $result);
608
609
                $result = $this->testDb->name('Model.name AS x');
610
                $expected = '`Model`.`name` AS `x`';
611
                $this->assertEquals($expected, $result);
612
613
                $result = $this->testDb->name('Function(Something.foo)');
614
                $expected = 'Function(`Something`.`foo`)';
615
                $this->assertEquals($expected, $result);
616
617
                $result = $this->testDb->name('Function(SubFunction(Something.foo))');
618
                $expected = 'Function(SubFunction(`Something`.`foo`))';
619
                $this->assertEquals($expected, $result);
620
621
                $result = $this->testDb->name('Function(Something.foo) AS x');
622
                $expected = 'Function(`Something`.`foo`) AS `x`';
623
                $this->assertEquals($expected, $result);
624
625
                $result = $this->testDb->name('I18n__title__pt-br.locale');
626
                $expected = '`I18n__title__pt-br`.`locale`';
627
                $this->assertEquals($expected, $result);
628
629
                $result = $this->testDb->name('name-with-minus');
630
                $expected = '`name-with-minus`';
631
                $this->assertEquals($expected, $result);
632
633
                $result = $this->testDb->name(array('my-name', 'Foo-Model.*'));
634
                $expected = array('`my-name`', '`Foo-Model`.*');
635
                $this->assertEquals($expected, $result);
636
637
                $result = $this->testDb->name(array('Team.P%', 'Team.G/G'));
638
                $expected = array('`Team`.`P%`', '`Team`.`G/G`');
639
                $this->assertEquals($expected, $result);
640
641
                $result = $this->testDb->name('Model.name as y');
642
                $expected = '`Model`.`name` AS `y`';
643
                $this->assertEquals($expected, $result);
644
        }
645
646
/**
647
 * test that cacheMethod works as expected
648
 *
649
 * @return void
650
 */
651
        public function testCacheMethod() {
652
                $this->testDb->cacheMethods = true;
653
                $result = $this->testDb->cacheMethod('name', 'some-key', 'stuff');
654
                $this->assertEquals('stuff', $result);
655
656
                $result = $this->testDb->cacheMethod('name', 'some-key');
657
                $this->assertEquals('stuff', $result);
658
659
                $result = $this->testDb->cacheMethod('conditions', 'some-key');
660
                $this->assertNull($result);
661
662
                $result = $this->testDb->cacheMethod('name', 'other-key');
663
                $this->assertNull($result);
664
665
                $this->testDb->cacheMethods = false;
666
                $result = $this->testDb->cacheMethod('name', 'some-key', 'stuff');
667
                $this->assertEquals('stuff', $result);
668
669
                $result = $this->testDb->cacheMethod('name', 'some-key');
670
                $this->assertNull($result);
671
        }
672
673
/**
674
 * Test that rare collisions do not happen with method caching
675
 *
676
 * @return void
677
 */
678
        public function testNameMethodCacheCollisions() {
679
                $this->testDb->cacheMethods = true;
680
                $this->testDb->flushMethodCache();
681
                $this->testDb->name('Model.fieldlbqndkezcoapfgirmjsh');
682
                $result = $this->testDb->name('Model.fieldkhdfjmelarbqnzsogcpi');
683
                $expected = '`Model`.`fieldkhdfjmelarbqnzsogcpi`';
684
                $this->assertEquals($expected, $result);
685
        }
686
687
/**
688
 * Test that flushMethodCache works as expected
689
 *
690
 * @return void
691
 */
692
        public function testFlushMethodCache() {
693
                $this->testDb->cacheMethods = true;
694
                $this->testDb->cacheMethod('name', 'some-key', 'stuff');
695
696
                Cache::write('method_cache', DboTestSource::$methodCache, '_cake_core_');
697
698
                $this->testDb->flushMethodCache();
699
                $result = $this->testDb->cacheMethod('name', 'some-key');
700
                $this->assertNull($result);
701
        }
702
703
/**
704
 * testLog method
705
 *
706
 * @outputBuffering enabled
707
 * @return void
708
 */
709
        public function testLog() {
710
                $this->testDb->logQuery('Query 1');
711
                $this->testDb->logQuery('Query 2');
712
713
                $log = $this->testDb->getLog(false, false);
714
                $result = Hash::extract($log['log'], '{n}.query');
715
                $expected = array('Query 1', 'Query 2');
716
                $this->assertEquals($expected, $result);
717
718
                $oldDebug = Configure::read('debug');
719
                Configure::write('debug', 2);
720
                ob_start();
721
                $this->testDb->showLog();
722
                $contents = ob_get_clean();
723
724
                $this->assertRegExp('/Query 1/s', $contents);
725
                $this->assertRegExp('/Query 2/s', $contents);
726
727
                ob_start();
728
                $this->testDb->showLog(true);
729
                $contents = ob_get_clean();
730
731
                $this->assertRegExp('/Query 1/s', $contents);
732
                $this->assertRegExp('/Query 2/s', $contents);
733
734
                Configure::write('debug', $oldDebug);
735
        }
736
737
/**
738
 * test getting the query log as an array.
739
 *
740
 * @return void
741
 */
742
        public function testGetLog() {
743
                $this->testDb->logQuery('Query 1');
744
                $this->testDb->logQuery('Query 2');
745
746
                $log = $this->testDb->getLog();
747
                $expected = array('query' => 'Query 1', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => '');
748
749
                $this->assertEquals($expected, $log['log'][0]);
750
                $expected = array('query' => 'Query 2', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => '');
751
                $this->assertEquals($expected, $log['log'][1]);
752
                $expected = array('query' => 'Error 1', 'affected' => '', 'numRows' => '', 'took' => '');
753
        }
754
755
/**
756
 * test getting the query log as an array, setting bind params.
757
 *
758
 * @return void
759
 */
760
        public function testGetLogParams() {
761
                $this->testDb->logQuery('Query 1', array(1, 2, 'abc'));
762
                $this->testDb->logQuery('Query 2', array('field1' => 1, 'field2' => 'abc'));
763
764
                $log = $this->testDb->getLog();
765
                $expected = array('query' => 'Query 1', 'params' => array(1, 2, 'abc'), 'affected' => '', 'numRows' => '', 'took' => '');
766
                $this->assertEquals($expected, $log['log'][0]);
767
                $expected = array('query' => 'Query 2', 'params' => array('field1' => 1, 'field2' => 'abc'), 'affected' => '', 'numRows' => '', 'took' => '');
768
                $this->assertEquals($expected, $log['log'][1]);
769
        }
770
771
/**
772
 * test that query() returns boolean values from operations like CREATE TABLE
773
 *
774
 * @return void
775
 */
776
        public function testFetchAllBooleanReturns() {
777
                $name = $this->db->fullTableName('test_query');
778
                $query = "CREATE TABLE {$name} (name varchar(10));";
779
                $result = $this->db->query($query);
780
                $this->assertTrue($result, 'Query did not return a boolean');
781
782
                $query = "DROP TABLE {$name};";
783
                $result = $this->db->query($query);
784
                $this->assertTrue($result, 'Query did not return a boolean');
785
        }
786
787
/**
788
 * Test NOT NULL on ENUM data type with empty string as a value
789
 *
790
 * @return void
791
 */
792
        public function testNotNullOnEnum() {
793
                if (!$this->db instanceof Mysql) {
794
                        $this->markTestSkipped('This test can only run on MySQL');
795
                }
796
                $name = $this->db->fullTableName('enum_tests');
797
                $query = "CREATE TABLE {$name} (mood ENUM('','happy','sad','ok') NOT NULL);";
798
                $result = $this->db->query($query);
799
                $this->assertTrue($result);
800
801
                $EnumTest = ClassRegistry::init('EnumTest');
802
                $enumResult = $EnumTest->save(array('mood' => ''));
803
804
                $query = "DROP TABLE {$name};";
805
                $result = $this->db->query($query);
806
                $this->assertTrue($result);
807
808
                $this->assertEquals(array(
809
                        'EnumTest' => array(
810
                                'mood' => '',
811
                                'id' => '0'
812
                        )
813
                ), $enumResult);
814
        }
815
816
/**
817
 * test order to generate query order clause for virtual fields
818
 *
819
 * @return void
820
 */
821
        public function testVirtualFieldsInOrder() {
822
                $Article = ClassRegistry::init('Article');
823
                $Article->virtualFields = array(
824
                        'this_moment' => 'NOW()',
825
                        'two' => '1 + 1',
826
                );
827
                $order = array('two', 'this_moment');
828
                $result = $this->db->order($order, 'ASC', $Article);
829
                $expected = ' ORDER BY (1 + 1) ASC, (NOW()) ASC';
830
                $this->assertEquals($expected, $result);
831
832
                $order = array('Article.two', 'Article.this_moment');
833
                $result = $this->db->order($order, 'ASC', $Article);
834
                $expected = ' ORDER BY (1 + 1) ASC, (NOW()) ASC';
835
                $this->assertEquals($expected, $result);
836
        }
837
838
/**
839
 * test the permutations of fullTableName()
840
 *
841
 * @return void
842
 */
843
        public function testFullTablePermutations() {
844
                $Article = ClassRegistry::init('Article');
845
                $result = $this->testDb->fullTableName($Article, false, false);
846
                $this->assertEquals('articles', $result);
847
848
                $Article->tablePrefix = 'tbl_';
849
                $result = $this->testDb->fullTableName($Article, false, false);
850
                $this->assertEquals('tbl_articles', $result);
851
852
                $Article->useTable = $Article->table = 'with spaces';
853
                $Article->tablePrefix = '';
854
                $result = $this->testDb->fullTableName($Article, true, false);
855
                $this->assertEquals('`with spaces`', $result);
856
857
                $this->loadFixtures('Article');
858
                $Article->useTable = $Article->table = 'articles';
859
                $Article->setDataSource('test');
860
                $testdb = $Article->getDataSource();
861
                $result = $testdb->fullTableName($Article, false, true);
862
                $this->assertEquals($testdb->getSchemaName() . '.articles', $result);
863
864
                // tests for empty schemaName
865
                $noschema = ConnectionManager::create('noschema', array(
866
                        'datasource' => 'DboTestSource'
867
                        ));
868
                $Article->setDataSource('noschema');
869
                $Article->schemaName = null;
870
                $result = $noschema->fullTableName($Article, false, true);
871
                $this->assertEquals('articles', $result);
872
873
                $this->testDb->config['prefix'] = 't_';
874
                $result = $this->testDb->fullTableName('post_tag', false, false);
875
                $this->assertEquals('t_post_tag', $result);
876
        }
877
878
/**
879
 * test that read() only calls queryAssociation on db objects when the method is defined.
880
 *
881
 * @return void
882
 */
883
        public function testReadOnlyCallingQueryAssociationWhenDefined() {
884
                $this->loadFixtures('Article', 'User', 'ArticlesTag', 'Tag');
885
                ConnectionManager::create('test_no_queryAssociation', array(
886
                        'datasource' => 'MockDataSource'
887
                ));
888
                $Article = ClassRegistry::init('Article');
889
                $Article->Comment->useDbConfig = 'test_no_queryAssociation';
890
                $result = $Article->find('all');
891
                $this->assertTrue(is_array($result));
892
        }
893
894
/**
895
 * test that queryAssociation() reuse already joined data for 'belongsTo' and 'hasOne' associations
896
 * instead of running unneeded queries for each record
897
 *
898
 * @return void
899
 */
900
        public function testQueryAssociationUnneededQueries() {
901
                $this->loadFixtures('Article', 'User', 'Comment', 'Attachment', 'Tag', 'ArticlesTag');
902
                $Comment = ClassRegistry::init('Comment');
903
904
                $fullDebug = $this->db->fullDebug;
905
                $this->db->fullDebug = true;
906
907
                $Comment->find('all', array('recursive' => 2)); // ensure Model descriptions are saved
908
                $this->db->getLog();
909
910
                // case: Comment belongsTo User and Article
911
                $Comment->unbindModel(array(
912
                        'hasOne' => array('Attachment')
913
                ));
914
                $Comment->Article->unbindModel(array(
915
                        'belongsTo' => array('User'),
916
                        'hasMany' => array('Comment'),
917
                        'hasAndBelongsToMany' => array('Tag')
918
                ));
919
                $Comment->find('all', array('recursive' => 2));
920
                $log = $this->db->getLog();
921
                $this->assertEquals(1, count($log['log']));
922
923
                // case: Comment belongsTo Article, Article belongsTo User
924
                $Comment->unbindModel(array(
925
                        'belongsTo' => array('User'),
926
                        'hasOne' => array('Attachment')
927
                ));
928
                $Comment->Article->unbindModel(array(
929
                        'hasMany' => array('Comment'),
930
                        'hasAndBelongsToMany' => array('Tag'),
931
                ));
932
                $Comment->find('all', array('recursive' => 2));
933
                $log = $this->db->getLog();
934
                $this->assertEquals(7, count($log['log']));
935
936
                // case: Comment hasOne Attachment
937
                $Comment->unbindModel(array(
938
                        'belongsTo' => array('Article', 'User'),
939
                ));
940
                $Comment->Attachment->unbindModel(array(
941
                        'belongsTo' => array('Comment'),
942
                ));
943
                $Comment->find('all', array('recursive' => 2));
944
                $log = $this->db->getLog();
945
                $this->assertEquals(1, count($log['log']));
946
947
                $this->db->fullDebug = $fullDebug;
948
        }
949
950
/**
951
 * Tests that generation association queries without LinkModel still works.
952
 * Mainly BC.
953
 *
954
 * @return void
955
 */
956
        public function testGenerateAssociationQuery() {
957
                $this->loadFixtures('Article');
958
                $Article = ClassRegistry::init('Article');
959
960
                $queryData = array(
961
                        'conditions' => array(
962
                                'Article.id' => 1
963
                        ),
964
                        'fields' => array(
965
                                'Article.id',
966
                                'Article.title',
967
                        ),
968
                        'joins' => array(),
969
                        'limit' => 2,
970
                        'offset' => 2,
971
                        'order' => array('title'),
972
                        'page' => 2,
973
                        'group' => null,
974
                        'callbacks' => 1
975
                );
976
977
                $result = $this->db->generateAssociationQuery($Article, null, null, null, null, $queryData, false);
978
                $this->assertContains('SELECT', $result);
979
                $this->assertContains('FROM', $result);
980
                $this->assertContains('WHERE', $result);
981
                $this->assertContains('ORDER', $result);
982
        }
983
984
/**
985
 * test that fields() is using methodCache()
986
 *
987
 * @return void
988
 */
989
        public function testFieldsUsingMethodCache() {
990
                $this->testDb->cacheMethods = false;
991
                DboTestSource::$methodCache = array();
992
993
                $Article = ClassRegistry::init('Article');
994
                $this->testDb->fields($Article, null, array('title', 'body', 'published'));
995
                $this->assertTrue(empty(DboTestSource::$methodCache['fields']), 'Cache not empty');
996
        }
997
998
/**
999
 * test that fields() method cache detects datasource changes
1000
 *
1001
 * @return void
1002
 */
1003
        public function testFieldsCacheKeyWithDatasourceChange() {
1004
                ConnectionManager::create('firstschema', array(
1005
                        'datasource' => 'DboTestSource'
1006
                ));
1007
                ConnectionManager::create('secondschema', array(
1008
                        'datasource' => 'DboSecondTestSource'
1009
                ));
1010
                Cache::delete('method_cache', '_cake_core_');
1011
                DboTestSource::$methodCache = array();
1012
                $Article = ClassRegistry::init('Article');
1013
1014
                $Article->setDataSource('firstschema');
1015
                $ds = $Article->getDataSource();
1016
                $ds->cacheMethods = true;
1017
                $first = $ds->fields($Article, null, array('title', 'body', 'published'));
1018
1019
                $Article->setDataSource('secondschema');
1020
                $ds = $Article->getDataSource();
1021
                $ds->cacheMethods = true;
1022
                $second = $ds->fields($Article, null, array('title', 'body', 'published'));
1023
1024
                $this->assertNotEquals($first, $second);
1025
                $this->assertEquals(2, count(DboTestSource::$methodCache['fields']));
1026
        }
1027
1028
/**
1029
 * test that fields() method cache detects schema name changes
1030
 *
1031
 * @return void
1032
 */
1033
        public function testFieldsCacheKeyWithSchemanameChange() {
1034
                if ($this->db instanceof Postgres || $this->db instanceof Sqlserver) {
1035
                        $this->markTestSkipped('Cannot run this test with SqlServer or Postgres');
1036
                }
1037
                Cache::delete('method_cache', '_cake_core_');
1038
                DboSource::$methodCache = array();
1039
                $Article = ClassRegistry::init('Article');
1040
1041
                $ds = $Article->getDataSource();
1042
                $ds->cacheMethods = true;
1043
                $first = $ds->fields($Article);
1044
1045
                $Article->schemaName = 'secondSchema';
1046
                $ds = $Article->getDataSource();
1047
                $ds->cacheMethods = true;
1048
                $second = $ds->fields($Article);
1049
1050
                $this->assertEquals(2, count(DboSource::$methodCache['fields']));
1051
        }
1052
1053
/**
1054
 * Test that group works without a model
1055
 *
1056
 * @return void
1057
 */
1058
        public function testGroupNoModel() {
1059
                $result = $this->db->group('created');
1060
                $this->assertEquals(' GROUP BY created', $result);
1061
        }
1062
1063
/**
1064
 * Test getting the last error.
1065
 *
1066
 * @return void
1067
 */
1068
        public function testLastError() {
1069
                $stmt = $this->getMock('PDOStatement');
1070
                $stmt->expects($this->any())
1071
                        ->method('errorInfo')
1072
                        ->will($this->returnValue(array('', 'something', 'bad')));
1073
1074
                $result = $this->db->lastError($stmt);
1075
                $expected = 'something: bad';
1076
                $this->assertEquals($expected, $result);
1077
        }
1078
1079
/**
1080
 * Tests that transaction commands are logged
1081
 *
1082
 * @return void
1083
 */
1084
        public function testTransactionLogging() {
1085
                $conn = $this->getMock('MockPDO');
1086
                $db = new DboTestSource();
1087
                $db->setConnection($conn);
1088
                $conn->expects($this->exactly(2))->method('beginTransaction')
1089
                        ->will($this->returnValue(true));
1090
                $conn->expects($this->once())->method('commit')->will($this->returnValue(true));
1091
                $conn->expects($this->once())->method('rollback')->will($this->returnValue(true));
1092
1093
                $db->begin();
1094
                $log = $db->getLog();
1095
                $expected = array('query' => 'BEGIN', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => '');
1096
                $this->assertEquals($expected, $log['log'][0]);
1097
1098
                $db->commit();
1099
                $expected = array('query' => 'COMMIT', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => '');
1100
                $log = $db->getLog();
1101
                $this->assertEquals($expected, $log['log'][0]);
1102
1103
                $db->begin();
1104
                $expected = array('query' => 'BEGIN', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => '');
1105
                $log = $db->getLog();
1106
                $this->assertEquals($expected, $log['log'][0]);
1107
1108
                $db->rollback();
1109
                $expected = array('query' => 'ROLLBACK', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => '');
1110
                $log = $db->getLog();
1111
                $this->assertEquals($expected, $log['log'][0]);
1112
        }
1113
1114
/**
1115
 * Test nested transaction calls
1116
 *
1117
 * @return void
1118
 */
1119
        public function testTransactionNested() {
1120
                $conn = $this->getMock('MockPDO');
1121
                $db = new DboTestSource();
1122
                $db->setConnection($conn);
1123
                $db->useNestedTransactions = true;
1124
                $db->nestedSupport = true;
1125
1126
                $conn->expects($this->at(0))->method('beginTransaction')->will($this->returnValue(true));
1127
                $conn->expects($this->at(1))->method('exec')->with($this->equalTo('SAVEPOINT LEVEL1'))->will($this->returnValue(true));
1128
                $conn->expects($this->at(2))->method('exec')->with($this->equalTo('RELEASE SAVEPOINT LEVEL1'))->will($this->returnValue(true));
1129
                $conn->expects($this->at(3))->method('exec')->with($this->equalTo('SAVEPOINT LEVEL1'))->will($this->returnValue(true));
1130
                $conn->expects($this->at(4))->method('exec')->with($this->equalTo('ROLLBACK TO SAVEPOINT LEVEL1'))->will($this->returnValue(true));
1131
                $conn->expects($this->at(5))->method('commit')->will($this->returnValue(true));
1132
1133
                $this->_runTransactions($db);
1134
        }
1135
1136
/**
1137
 * Test nested transaction calls without support
1138
 *
1139
 * @return void
1140
 */
1141
        public function testTransactionNestedWithoutSupport() {
1142
                $conn = $this->getMock('MockPDO');
1143
                $db = new DboTestSource();
1144
                $db->setConnection($conn);
1145
                $db->useNestedTransactions = true;
1146
                $db->nestedSupport = false;
1147
1148
                $conn->expects($this->once())->method('beginTransaction')->will($this->returnValue(true));
1149
                $conn->expects($this->never())->method('exec');
1150
                $conn->expects($this->once())->method('commit')->will($this->returnValue(true));
1151
1152
                $this->_runTransactions($db);
1153
        }
1154
1155
/**
1156
 * Test nested transaction disabled
1157
 *
1158
 * @return void
1159
 */
1160
        public function testTransactionNestedDisabled() {
1161
                $conn = $this->getMock('MockPDO');
1162
                $db = new DboTestSource();
1163
                $db->setConnection($conn);
1164
                $db->useNestedTransactions = false;
1165
                $db->nestedSupport = true;
1166
1167
                $conn->expects($this->once())->method('beginTransaction')->will($this->returnValue(true));
1168
                $conn->expects($this->never())->method('exec');
1169
                $conn->expects($this->once())->method('commit')->will($this->returnValue(true));
1170
1171
                $this->_runTransactions($db);
1172
        }
1173
1174
/**
1175
 * Nested transaction calls
1176
 *
1177
 * @param DboTestSource $db
1178
 * @return void
1179
 */
1180
        protected function _runTransactions($db) {
1181
                $db->begin();
1182
                $db->begin();
1183
                $db->commit();
1184
                $db->begin();
1185
                $db->rollback();
1186
                $db->commit();
1187
        }
1188
1189
/**
1190
 * Test build statement with some fields missing
1191
 *
1192
 * @return void
1193
 */
1194
        public function testBuildStatementDefaults() {
1195
                $conn = $this->getMock('MockPDO', array('quote'));
1196
                $conn->expects($this->at(0))
1197
                        ->method('quote')
1198
                        ->will($this->returnValue('foo bar'));
1199
                $db = new DboTestSource();
1200
                $db->setConnection($conn);
1201
                $subQuery = $db->buildStatement(
1202
                        array(
1203
                                'fields' => array('DISTINCT(AssetsTag.asset_id)'),
1204
                                'table' => "assets_tags",
1205
                                'alias' => "AssetsTag",
1206
                                'conditions' => array("Tag.name" => 'foo bar'),
1207
                                'limit' => null,
1208
                                'group' => "AssetsTag.asset_id"
1209
                        ),
1210
                        $this->Model
1211
                );
1212
                $expected = 'SELECT DISTINCT(AssetsTag.asset_id) FROM assets_tags AS AssetsTag   WHERE Tag.name = foo bar  GROUP BY AssetsTag.asset_id';
1213
                $this->assertEquals($expected, $subQuery);
1214
        }
1215
1216
/**
1217
 * data provider for testBuildJoinStatement
1218
 *
1219
 * @return array
1220
 */
1221
        public static function joinStatements() {
1222
                return array(
1223
                        array(array(
1224
                                'type' => 'CROSS',
1225
                                'alias' => 'PostsTag',
1226
                                'table' => 'posts_tags',
1227
                                'conditions' => array('1 = 1')
1228
                        ), 'CROSS JOIN cakephp.posts_tags AS PostsTag'),
1229
                        array(array(
1230
                                'type' => 'LEFT',
1231
                                'alias' => 'PostsTag',
1232
                                'table' => 'posts_tags',
1233
                        ), 'LEFT JOIN cakephp.posts_tags AS PostsTag'),
1234
                        array(array(
1235
                                'type' => 'LEFT',
1236
                                'alias' => 'PostsTag',
1237
                                'table' => 'posts_tags',
1238
                                'conditions' => array('PostsTag.post_id = Post.id')
1239
                        ), 'LEFT JOIN cakephp.posts_tags AS PostsTag ON (PostsTag.post_id = Post.id)'),
1240
                        array(array(
1241
                                'type' => 'LEFT',
1242
                                'alias' => 'Stock',
1243
                                'table' => '(SELECT Stock.article_id, sum(quantite) quantite FROM stocks AS Stock GROUP BY Stock.article_id)',
1244
                                'conditions' => 'Stock.article_id = Article.id'
1245
                        ), 'LEFT JOIN (SELECT Stock.article_id, sum(quantite) quantite FROM stocks AS Stock GROUP BY Stock.article_id) AS Stock ON (Stock.article_id = Article.id)')
1246
                );
1247
        }
1248
1249
/**
1250
 * Test buildJoinStatement()
1251
 * ensure that schemaName is not added when table value is a subquery
1252
 *
1253
 * @dataProvider joinStatements
1254
 * @return void
1255
 */
1256
        public function testBuildJoinStatement($join, $expected) {
1257
                $db = $this->getMock('DboTestSource', array('getSchemaName'));
1258
                $db->expects($this->any())
1259
                        ->method('getSchemaName')
1260
                        ->will($this->returnValue('cakephp'));
1261
                $result = $db->buildJoinStatement($join);
1262
                $this->assertEquals($expected, $result);
1263
        }
1264
1265
/**
1266
 * data provider for testBuildJoinStatementWithTablePrefix
1267
 *
1268
 * @return array
1269
 */
1270
        public static function joinStatementsWithPrefix($schema) {
1271
                return array(
1272
                        array(array(
1273
                                'type' => 'LEFT',
1274
                                'alias' => 'PostsTag',
1275
                                'table' => 'posts_tags',
1276
                                'conditions' => array('PostsTag.post_id = Post.id')
1277
                        ), 'LEFT JOIN pre_posts_tags AS PostsTag ON (PostsTag.post_id = Post.id)'),
1278
                                array(array(
1279
                                        'type' => 'LEFT',
1280
                                        'alias' => 'Stock',
1281
                                        'table' => '(SELECT Stock.article_id, sum(quantite) quantite FROM stocks AS Stock GROUP BY Stock.article_id)',
1282
                                        'conditions' => 'Stock.article_id = Article.id'
1283
                                ), 'LEFT JOIN (SELECT Stock.article_id, sum(quantite) quantite FROM stocks AS Stock GROUP BY Stock.article_id) AS Stock ON (Stock.article_id = Article.id)')
1284
                        );
1285
        }
1286
1287
/**
1288
 * Test buildJoinStatement()
1289
 * ensure that prefix is not added when table value is a subquery
1290
 *
1291
 * @dataProvider joinStatementsWithPrefix
1292
 * @return void
1293
 */
1294
        public function testBuildJoinStatementWithTablePrefix($join, $expected) {
1295
                $db = new DboTestSource();
1296
                $db->config['prefix'] = 'pre_';
1297
                $result = $db->buildJoinStatement($join);
1298
                $this->assertEquals($expected, $result);
1299
        }
1300
1301
/**
1302
 * Test conditionKeysToString()
1303
 *
1304
 * @return void
1305
 */
1306
        public function testConditionKeysToString() {
1307
                $Article = ClassRegistry::init('Article');
1308
                $conn = $this->getMock('MockPDO', array('quote'));
1309
                $db = new DboTestSource();
1310
                $db->setConnection($conn);
1311
1312
                $conn->expects($this->at(0))
1313
                        ->method('quote')
1314
                        ->will($this->returnValue('just text'));
1315
1316
                $conditions = array('Article.name' => 'just text');
1317
                $result = $db->conditionKeysToString($conditions, true, $Article);
1318
                $expected = "Article.name = just text";
1319
                $this->assertEquals($expected, $result[0]);
1320
1321
                $conn->expects($this->at(0))
1322
                        ->method('quote')
1323
                        ->will($this->returnValue('just text'));
1324
                $conn->expects($this->at(1))
1325
                        ->method('quote')
1326
                        ->will($this->returnValue('other text'));
1327
1328
                $conditions = array('Article.name' => array('just text', 'other text'));
1329
                $result = $db->conditionKeysToString($conditions, true, $Article);
1330
                $expected = "Article.name IN (just text, other text)";
1331
                $this->assertEquals($expected, $result[0]);
1332
        }
1333
1334
/**
1335
 * Test conditionKeysToString() with virtual field
1336
 *
1337
 * @return void
1338
 */
1339
        public function testConditionKeysToStringVirtualField() {
1340
                $Article = ClassRegistry::init('Article');
1341
                $Article->virtualFields = array(
1342
                        'extra' => 'something virtual'
1343
                );
1344
                $conn = $this->getMock('MockPDO', array('quote'));
1345
                $db = new DboTestSource();
1346
                $db->setConnection($conn);
1347
1348
                $conn->expects($this->at(0))
1349
                        ->method('quote')
1350
                        ->will($this->returnValue('just text'));
1351
1352
                $conditions = array('Article.extra' => 'just text');
1353
                $result = $db->conditionKeysToString($conditions, true, $Article);
1354
                $expected = "(" . $Article->virtualFields['extra'] . ") = just text";
1355
                $this->assertEquals($expected, $result[0]);
1356
1357
                $conn->expects($this->at(0))
1358
                        ->method('quote')
1359
                        ->will($this->returnValue('just text'));
1360
                $conn->expects($this->at(1))
1361
                        ->method('quote')
1362
                        ->will($this->returnValue('other text'));
1363
1364
                $conditions = array('Article.extra' => array('just text', 'other text'));
1365
                $result = $db->conditionKeysToString($conditions, true, $Article);
1366
                $expected = "(" . $Article->virtualFields['extra'] . ") IN (just text, other text)";
1367
                $this->assertEquals($expected, $result[0]);
1368
        }
1369
1370
/**
1371
 * Test the limit function.
1372
 *
1373
 * @return void
1374
 */
1375
        public function testLimit() {
1376
                $db = new DboTestSource();
1377
1378
                $result = $db->limit('0');
1379
                $this->assertNull($result);
1380
1381
                $result = $db->limit('10');
1382
                $this->assertEquals(' LIMIT 10', $result);
1383
1384
                $result = $db->limit('FARTS', 'BOOGERS');
1385
                $this->assertEquals(' LIMIT 0, 0', $result);
1386
1387
                $result = $db->limit(20, 10);
1388
                $this->assertEquals(' LIMIT 10, 20', $result);
1389
1390
                $result = $db->limit(10, 300000000000000000000000000000);
1391
                $scientificNotation = sprintf('%.1E', 300000000000000000000000000000);
1392
                $this->assertNotContains($scientificNotation, $result);
1393
        }
1394
1395
/**
1396
 * Test insertMulti with id position.
1397
 *
1398
 * @return void
1399
 */
1400
        public function testInsertMultiId() {
1401
                $this->loadFixtures('Article');
1402
                $Article = ClassRegistry::init('Article');
1403
                $db = $Article->getDatasource();
1404
                $datetime = date('Y-m-d H:i:s');
1405
                $data = array(
1406
                        array(
1407
                                'user_id' => 1,
1408
                                'title' => 'test',
1409
                                'body' => 'test',
1410
                                'published' => 'N',
1411
                                'created' => $datetime,
1412
                                'updated' => $datetime,
1413
                                'id' => 100,
1414
                        ),
1415
                        array(
1416
                                'user_id' => 1,
1417
                                'title' => 'test 101',
1418
                                'body' => 'test 101',
1419
                                'published' => 'N',
1420
                                'created' => $datetime,
1421
                                'updated' => $datetime,
1422
                                'id' => 101,
1423
                        )
1424
                );
1425
                $result = $db->insertMulti('articles', array_keys($data[0]), $data);
1426
                $this->assertTrue($result, 'Data was saved');
1427
1428
                $data = array(
1429
                        array(
1430
                                'id' => 102,
1431
                                'user_id' => 1,
1432
                                'title' => 'test',
1433
                                'body' => 'test',
1434
                                'published' => 'N',
1435
                                'created' => $datetime,
1436
                                'updated' => $datetime,
1437
                        ),
1438
                        array(
1439
                                'id' => 103,
1440
                                'user_id' => 1,
1441
                                'title' => 'test 101',
1442
                                'body' => 'test 101',
1443
                                'published' => 'N',
1444
                                'created' => $datetime,
1445
                                'updated' => $datetime,
1446
                        )
1447
                );
1448
1449
                $result = $db->insertMulti('articles', array_keys($data[0]), $data);
1450
                $this->assertTrue($result, 'Data was saved');
1451
        }
1452
1453
/**
1454
 * Test defaultConditions()
1455
 *
1456
 * @return void
1457
 */
1458
        public function testDefaultConditions() {
1459
                $this->loadFixtures('Article');
1460
                $Article = ClassRegistry::init('Article');
1461
                $db = $Article->getDataSource();
1462
1463
                // Creates a default set of conditions from the model if $conditions is null/empty.
1464
                $Article->id = 1;
1465
                $result = $db->defaultConditions($Article, null);
1466
                $this->assertEquals(array('Article.id' => 1), $result);
1467
1468
                // $useAlias == false
1469
                $Article->id = 1;
1470
                $result = $db->defaultConditions($Article, null, false);
1471
                $this->assertEquals(array($db->fullTableName($Article, false) . '.id' => 1), $result);
1472
1473
                // If conditions are supplied then they will be returned.
1474
                $Article->id = 1;
1475
                $result = $db->defaultConditions($Article, array('Article.title' => 'First article'));
1476
                $this->assertEquals(array('Article.title' => 'First article'), $result);
1477
1478
                // If a model doesn't exist and no conditions were provided either null or false will be returned based on what was input.
1479
                $Article->id = 1000000;
1480
                $result = $db->defaultConditions($Article, null);
1481
                $this->assertNull($result);
1482
1483
                $Article->id = 1000000;
1484
                $result = $db->defaultConditions($Article, false);
1485
                $this->assertFalse($result);
1486
1487
                // Safe update mode
1488
                $Article->id = 1000000;
1489
                $Article->__safeUpdateMode = true;
1490
                $result = $db->defaultConditions($Article, null);
1491
                $this->assertFalse($result);
1492
        }
1493
1494
/**
1495
 * Test that count how many times afterFind is called
1496
 *
1497
 * @return void
1498
 */
1499
        public function testCountAfterFindCalls() {
1500
                $this->loadFixtures('Article', 'User', 'Comment', 'Attachment', 'Tag', 'ArticlesTag');
1501
1502
                // Use alias to make testing "primary = true" easy
1503
                $Primary = $this->getMock('Comment', array('afterFind'), array(array('alias' => 'Primary')), '', true);
1504
1505
                $Article = $this->getMock('Article', array('afterFind'), array(), '', true);
1506
                $User = $this->getMock('User', array('afterFind'), array(), '', true);
1507
                $Comment = $this->getMock('Comment', array('afterFind'), array(), '', true);
1508
                $Tag = $this->getMock('Tag', array('afterFind'), array(), '', true);
1509
                $Attachment = $this->getMock('Attachment', array('afterFind'), array(), '', true);
1510
1511
                $Primary->Article = $Article;
1512
                $Primary->Article->User = $User;
1513
                $Primary->Article->Tag = $Tag;
1514
                $Primary->Article->Comment = $Comment;
1515
                $Primary->Attachment = $Attachment;
1516
                $Primary->Attachment->Comment = $Comment;
1517
                $Primary->User = $User;
1518
1519
                // primary = true
1520
                $Primary->expects($this->once())
1521
                        ->method('afterFind')->with($this->anything(), $this->isTrue())->will($this->returnArgument(0));
1522
1523
                // primary = false
1524
                $Article->expects($this->once()) // Primary belongs to 1 Article
1525
                        ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
1526
                $User->expects($this->exactly(2)) // Article belongs to 1 User and Primary belongs to 1 User
1527
                        ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
1528
                $Tag->expects($this->exactly(2)) // Article has 2 Tags
1529
                        ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
1530
                $Comment->expects($this->exactly(3)) // Article has 2 Comments and Attachment belongs to 1 Comment
1531
                        ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
1532
                $Attachment->expects($this->once()) // Primary has 1 Attachment
1533
                        ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
1534
1535
                $result = $Primary->find('first', array('conditions' => array('Primary.id' => 5), 'recursive' => 2));
1536
                $this->assertCount(2, $result['Article']['Tag']);
1537
                $this->assertCount(2, $result['Article']['Comment']);
1538
1539
                // hasMany special case
1540
                // Both User and Article has many Comments
1541
                $User = $this->getMock('User', array('afterFind'), array(), '', true);
1542
                $Article = $this->getMock('Article', array('afterFind'), array(), '', true);
1543
                $Comment = $this->getMock('Comment', array('afterFind'), array(), '', true);
1544
1545
                $User->bindModel(array('hasMany' => array('Comment', 'Article')));
1546
                $Article->unbindModel(array('belongsTo' => array('User'), 'hasAndBelongsToMany' => array('Tag')));
1547
                $Comment->unbindModel(array('belongsTo' => array('User', 'Article'), 'hasOne' => 'Attachment'));
1548
1549
                $User->Comment = $Comment;
1550
                $User->Article = $Article;
1551
                $User->Article->Comment = $Comment;
1552
1553
                // primary = true
1554
                $User->expects($this->once())
1555
                        ->method('afterFind')->with($this->anything(), $this->isTrue())->will($this->returnArgument(0));
1556
1557
                $Article->expects($this->exactly(2)) // User has 2 Articles
1558
                        ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
1559
1560
                $Comment->expects($this->exactly(7)) // User1 has 3 Comments, Article[id=1] has 4 Comments and Article[id=3] has 0 Comments
1561
                        ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0));
1562
1563
                $result = $User->find('first', array('conditions' => array('User.id' => 1), 'recursive' => 2));
1564
                $this->assertCount(3, $result['Comment']);
1565
                $this->assertCount(2, $result['Article']);
1566
                $this->assertCount(4, $result['Article'][0]['Comment']);
1567
                $this->assertCount(0, $result['Article'][1]['Comment']);
1568
        }
1569
1570
/**
1571
 * Test format of $results in afterFind
1572
 *
1573
 * @return void
1574
 */
1575
        public function testUseConsistentAfterFind() {
1576
                $this->loadFixtures('Author', 'Post');
1577
1578
                $expected = array(
1579
                        'Author' => array(
1580
                                'id' => '1',
1581
                                'user' => 'mariano',
1582
                                'password' => '5f4dcc3b5aa765d61d8327deb882cf99',
1583
                                'created' => '2007-03-17 01:16:23',
1584
                                'updated' => '2007-03-17 01:18:31',
1585
                                'test' => 'working',
1586
                        ),
1587
                        'Post' => array(
1588
                                array(
1589
                                        'id' => '1',
1590
                                        'author_id' => '1',
1591
                                        'title' => 'First Post',
1592
                                        'body' => 'First Post Body',
1593
                                        'published' => 'Y',
1594
                                        'created' => '2007-03-18 10:39:23',
1595
                                        'updated' => '2007-03-18 10:41:31',
1596
                                ),
1597
                                array(
1598
                                        'id' => '3',
1599
                                        'author_id' => '1',
1600
                                        'title' => 'Third Post',
1601
                                        'body' => 'Third Post Body',
1602
                                        'published' => 'Y',
1603
                                        'created' => '2007-03-18 10:43:23',
1604
                                        'updated' => '2007-03-18 10:45:31',
1605
                                ),
1606
                        ),
1607
                );
1608
1609
                $Author = new Author();
1610
                $Post = $this->getMock('Post', array('afterFind'), array(), '', true);
1611
                $Post->expects($this->at(0))->method('afterFind')->with(array(array('Post' => $expected['Post'][0])), $this->isFalse())->will($this->returnArgument(0));
1612
                $Post->expects($this->at(1))->method('afterFind')->with(array(array('Post' => $expected['Post'][1])), $this->isFalse())->will($this->returnArgument(0));
1613
1614
                $Author->bindModel(array('hasMany' => array('Post' => array('limit' => 2, 'order' => 'Post.id'))));
1615
                $Author->Post = $Post;
1616
1617
                $result = $Author->find('first', array('conditions' => array('Author.id' => 1), 'recursive' => 1));
1618
                $this->assertEquals($expected, $result);
1619
1620
                // Backward compatiblity
1621
                $Author = new Author();
1622
                $Post = $this->getMock('Post', array('afterFind'), array(), '', true);
1623
                $Post->expects($this->once())->method('afterFind')->with($expected['Post'], $this->isFalse())->will($this->returnArgument(0));
1624
                $Post->useConsistentAfterFind = false;
1625
1626
                $Author->bindModel(array('hasMany' => array('Post' => array('limit' => 2, 'order' => 'Post.id'))));
1627
                $Author->Post = $Post;
1628
1629
                $result = $Author->find('first', array('conditions' => array('Author.id' => 1), 'recursive' => 1));
1630
                $this->assertEquals($expected, $result);
1631
        }
1632
1633
/**
1634
 * Test that afterFind is called correctly for 'joins'
1635
 *
1636
 * @return void
1637
 */
1638
        public function testJoinsAfterFind() {
1639
                $this->loadFixtures('Article', 'User');
1640
1641
                $User = new User();
1642
                $User->bindModel(array('hasOne' => array('Article')));
1643
1644
                $Article = $this->getMock('Article', array('afterFind'), array(), '', true);
1645
                $Article->expects($this->once())
1646
                        ->method('afterFind')
1647
                        ->with(
1648
                                array(
1649
                                        0 => array(
1650
                                                'Article' => array(
1651
                                                        'id' => '1',
1652
                                                        'user_id' => '1',
1653
                                                        'title' => 'First Article',
1654
                                                        'body' => 'First Article Body',
1655
                                                        'published' => 'Y',
1656
                                                        'created' => '2007-03-18 10:39:23',
1657
                                                        'updated' => '2007-03-18 10:41:31'
1658
                                                )
1659
                                        )
1660
                                ),
1661
                                $this->isFalse()
1662
                        )
1663
                        ->will($this->returnArgument(0));
1664
1665
                $User->Article = $Article;
1666
                $User->find('first', array(
1667
                        'fields' => array(
1668
                                'Article.id',
1669
                                'Article.user_id',
1670
                                'Article.title',
1671
                                'Article.body',
1672
                                'Article.published',
1673
                                'Article.created',
1674
                                'Article.updated'
1675
                        ),
1676
                        'conditions' => array('User.id' => 1),
1677
                        'recursive' => -1,
1678
                        'joins' => array(
1679
                                array(
1680
                                        'table' => 'articles',
1681
                                        'alias' => 'Article',
1682
                                        'type' => 'LEFT',
1683
                                        'conditions' => array(
1684
                                                'Article.user_id = User.id'
1685
                                        ),
1686
                                )
1687
                        ),
1688
                        'order' => array('Article.id')
1689
                ));
1690
        }
1691
1692
/**
1693
 * Test that afterFind is called correctly for 'hasOne' association.
1694
 *
1695
 * @return void
1696
 */
1697
        public function testHasOneAfterFind() {
1698
                $this->loadFixtures('Article', 'User', 'Comment');
1699
1700
                $User = new User();
1701
                $User->bindModel(array('hasOne' => array('Article')));
1702
1703
                $Article = $this->getMock('Article', array('afterFind'), array(), '', true);
1704
                $Article->unbindModel(array(
1705
                        'belongsTo' => array('User'),
1706
                        'hasMany' => array('Comment'),
1707
                        'hasAndBelongsToMany' => array('Tag')
1708
                ));
1709
                $Article->bindModel(array(
1710
                        'hasOne' => array('Comment'),
1711
                ));
1712
                $Article->expects($this->once())
1713
                        ->method('afterFind')
1714
                        ->with(
1715
                                $this->equalTo(
1716
                                        array(
1717
                                                0 => array(
1718
                                                        'Article' => array(
1719
                                                                'id' => '1',
1720
                                                                'user_id' => '1',
1721
                                                                'title' => 'First Article',
1722
                                                                'body' => 'First Article Body',
1723
                                                                'published' => 'Y',
1724
                                                                'created' => '2007-03-18 10:39:23',
1725
                                                                'updated' => '2007-03-18 10:41:31',
1726
                                                                'Comment' => array(
1727
                                                                        'id' => '1',
1728
                                                                        'article_id' => '1',
1729
                                                                        'user_id' => '2',
1730
                                                                        'comment' => 'First Comment for First Article',
1731
                                                                        'published' => 'Y',
1732
                                                                        'created' => '2007-03-18 10:45:23',
1733
                                                                        'updated' => '2007-03-18 10:47:31',
1734
                                                                )
1735
                                                        )
1736
                                                )
1737
                                        )
1738
                                ),
1739
                                $this->isFalse()
1740
                        )
1741
                        ->will($this->returnArgument(0));
1742
1743
                $User->Article = $Article;
1744
                $User->find('first', array('conditions' => array('User.id' => 1), 'recursive' => 2));
1745
        }
1746
}