Passed
Pull Request — master (#3120)
by Sergei
12:25
created

DataAccessTest   F

Complexity

Total Complexity 68

Size/Duplication

Total Lines 869
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 68
dl 0
loc 869
rs 2.3529
c 0
b 0
f 0

How to fix   Complexity   

Complex Class

Complex classes like DataAccessTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DataAccessTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Doctrine\Tests\DBAL\Functional;
4
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\FetchMode;
7
use Doctrine\DBAL\ParameterType;
8
use Doctrine\DBAL\Platforms\AbstractPlatform;
9
use Doctrine\DBAL\Platforms\TrimMode;
10
use Doctrine\DBAL\Types\Type;
11
use const CASE_LOWER;
12
use const PHP_EOL;
13
use function array_change_key_case;
14
use function array_filter;
15
use function array_keys;
16
use function count;
17
use function date;
18
use function implode;
19
use function is_numeric;
20
use function json_encode;
21
use function property_exists;
22
use function strtotime;
23
24
class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase
25
{
26
    /**
27
     * @var bool
28
     */
29
    static private $generated = false;
30
31
    protected function setUp()
32
    {
33
        parent::setUp();
34
35
        if (self::$generated === false) {
36
            /* @var $sm \Doctrine\DBAL\Schema\AbstractSchemaManager */
37
            $table = new \Doctrine\DBAL\Schema\Table("fetch_table");
38
            $table->addColumn('test_int', 'integer');
39
            $table->addColumn('test_string', 'string');
40
            $table->addColumn('test_datetime', 'datetime', array('notnull' => false));
41
            $table->setPrimaryKey(array('test_int'));
42
43
            $sm = $this->_conn->getSchemaManager();
44
            $sm->createTable($table);
45
46
            $this->_conn->insert('fetch_table', array('test_int' => 1, 'test_string' => 'foo', 'test_datetime' => '2010-01-01 10:10:10'));
47
            self::$generated = true;
48
        }
49
    }
50
51
    public function testPrepareWithBindValue()
52
    {
53
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
54
        $stmt = $this->_conn->prepare($sql);
55
        self::assertInstanceOf('Doctrine\DBAL\Statement', $stmt);
56
57
        $stmt->bindValue(1, 1);
58
        $stmt->bindValue(2, 'foo');
59
        $stmt->execute();
60
61
        $row = $stmt->fetch(FetchMode::ASSOCIATIVE);
62
        $row = array_change_key_case($row, \CASE_LOWER);
63
        self::assertEquals(array('test_int' => 1, 'test_string' => 'foo'), $row);
64
    }
65
66
    public function testPrepareWithBindParam()
67
    {
68
        $paramInt = 1;
69
        $paramStr = 'foo';
70
71
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
72
        $stmt = $this->_conn->prepare($sql);
73
        self::assertInstanceOf('Doctrine\DBAL\Statement', $stmt);
74
75
        $stmt->bindParam(1, $paramInt);
76
        $stmt->bindParam(2, $paramStr);
77
        $stmt->execute();
78
79
        $row = $stmt->fetch(FetchMode::ASSOCIATIVE);
80
        $row = array_change_key_case($row, \CASE_LOWER);
81
        self::assertEquals(array('test_int' => 1, 'test_string' => 'foo'), $row);
82
    }
83
84
    public function testPrepareWithFetchAll()
85
    {
86
        $paramInt = 1;
87
        $paramStr = 'foo';
88
89
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
90
        $stmt = $this->_conn->prepare($sql);
91
        self::assertInstanceOf('Doctrine\DBAL\Statement', $stmt);
92
93
        $stmt->bindParam(1, $paramInt);
94
        $stmt->bindParam(2, $paramStr);
95
        $stmt->execute();
96
97
        $rows    = $stmt->fetchAll(FetchMode::ASSOCIATIVE);
98
        $rows[0] = array_change_key_case($rows[0], \CASE_LOWER);
99
        self::assertEquals(array('test_int' => 1, 'test_string' => 'foo'), $rows[0]);
100
    }
101
102
    /**
103
     * @group DBAL-228
104
     */
105
    public function testPrepareWithFetchAllBoth()
106
    {
107
        $paramInt = 1;
108
        $paramStr = 'foo';
109
110
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
111
        $stmt = $this->_conn->prepare($sql);
112
        self::assertInstanceOf('Doctrine\DBAL\Statement', $stmt);
113
114
        $stmt->bindParam(1, $paramInt);
115
        $stmt->bindParam(2, $paramStr);
116
        $stmt->execute();
117
118
        $rows    = $stmt->fetchAll(FetchMode::MIXED);
119
        $rows[0] = array_change_key_case($rows[0], \CASE_LOWER);
120
        self::assertEquals(array('test_int' => 1, 'test_string' => 'foo', 0 => 1, 1 => 'foo'), $rows[0]);
121
    }
122
123
    public function testPrepareWithFetchColumn()
124
    {
125
        $paramInt = 1;
126
        $paramStr = 'foo';
127
128
        $sql = "SELECT test_int FROM fetch_table WHERE test_int = ? AND test_string = ?";
129
        $stmt = $this->_conn->prepare($sql);
130
        self::assertInstanceOf('Doctrine\DBAL\Statement', $stmt);
131
132
        $stmt->bindParam(1, $paramInt);
133
        $stmt->bindParam(2, $paramStr);
134
        $stmt->execute();
135
136
        $column = $stmt->fetchColumn();
137
        self::assertEquals(1, $column);
138
    }
139
140
    public function testPrepareWithIterator()
141
    {
142
        $paramInt = 1;
143
        $paramStr = 'foo';
144
145
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
146
        $stmt = $this->_conn->prepare($sql);
147
        self::assertInstanceOf('Doctrine\DBAL\Statement', $stmt);
148
149
        $stmt->bindParam(1, $paramInt);
150
        $stmt->bindParam(2, $paramStr);
151
        $stmt->execute();
152
153
        $rows = array();
154
        $stmt->setFetchMode(FetchMode::ASSOCIATIVE);
155
        foreach ($stmt as $row) {
156
            $rows[] = array_change_key_case($row, \CASE_LOWER);
157
        }
158
159
        self::assertEquals(array('test_int' => 1, 'test_string' => 'foo'), $rows[0]);
160
    }
161
162
    public function testPrepareWithQuoted()
163
    {
164
        $table = 'fetch_table';
165
        $paramInt = 1;
166
        $paramStr = 'foo';
167
168
        $sql = "SELECT test_int, test_string FROM " . $this->_conn->quoteIdentifier($table) . " ".
169
               "WHERE test_int = " . $this->_conn->quote($paramInt) . " AND test_string = " . $this->_conn->quote($paramStr);
170
        $stmt = $this->_conn->prepare($sql);
171
        self::assertInstanceOf('Doctrine\DBAL\Statement', $stmt);
172
    }
173
174
    public function testPrepareWithExecuteParams()
175
    {
176
        $paramInt = 1;
177
        $paramStr = 'foo';
178
179
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
180
        $stmt = $this->_conn->prepare($sql);
181
        self::assertInstanceOf('Doctrine\DBAL\Statement', $stmt);
182
        $stmt->execute(array($paramInt, $paramStr));
183
184
        $row = $stmt->fetch(FetchMode::ASSOCIATIVE);
185
        self::assertNotFalse($row);
186
        $row = array_change_key_case($row, \CASE_LOWER);
187
        self::assertEquals(array('test_int' => 1, 'test_string' => 'foo'), $row);
188
    }
189
190
    public function testFetchAll()
191
    {
192
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
193
        $data = $this->_conn->fetchAll($sql, array(1, 'foo'));
194
195
        self::assertCount(1, $data);
196
197
        $row = $data[0];
198
        self::assertCount(2, $row);
199
200
        $row = array_change_key_case($row, \CASE_LOWER);
201
        self::assertEquals(1, $row['test_int']);
202
        self::assertEquals('foo', $row['test_string']);
203
    }
204
205
    /**
206
     * @group DBAL-209
207
     */
208
    public function testFetchAllWithTypes()
209
    {
210
        $datetimeString = '2010-01-01 10:10:10';
211
        $datetime = new \DateTime($datetimeString);
212
213
        $sql  = 'SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?';
214
        $data = $this->_conn->fetchAll($sql, [1, $datetime], [ParameterType::STRING, Type::DATETIME]);
215
216
        self::assertCount(1, $data);
217
218
        $row = $data[0];
219
        self::assertCount(2, $row);
220
221
        $row = array_change_key_case($row, \CASE_LOWER);
222
        self::assertEquals(1, $row['test_int']);
223
        self::assertStringStartsWith($datetimeString, $row['test_datetime']);
224
    }
225
226
    /**
227
     * @group DBAL-209
228
     * @expectedException \Doctrine\DBAL\DBALException
229
     */
230
    public function testFetchAllWithMissingTypes()
231
    {
232
        if ($this->_conn->getDriver() instanceof \Doctrine\DBAL\Driver\Mysqli\Driver ||
233
            $this->_conn->getDriver() instanceof \Doctrine\DBAL\Driver\SQLSrv\Driver) {
234
            $this->markTestSkipped('mysqli and sqlsrv actually supports this');
235
        }
236
237
        $datetimeString = '2010-01-01 10:10:10';
238
        $datetime = new \DateTime($datetimeString);
239
        $sql = "SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?";
240
        $data = $this->_conn->fetchAll($sql, array(1, $datetime));
241
    }
242
243
    public function testFetchBoth()
244
    {
245
        $sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?';
246
        $row = $this->_conn->executeQuery($sql, [1, 'foo'])->fetch(FetchMode::MIXED);
247
248
        self::assertNotFalse($row);
249
250
        $row = array_change_key_case($row, \CASE_LOWER);
251
252
        self::assertEquals(1, $row['test_int']);
253
        self::assertEquals('foo', $row['test_string']);
254
        self::assertEquals(1, $row[0]);
255
        self::assertEquals('foo', $row[1]);
256
    }
257
258
    public function testFetchNoResult()
259
    {
260
        self::assertFalse(
261
            $this->_conn->executeQuery('SELECT test_int FROM fetch_table WHERE test_int = ?', [-1])->fetch()
262
        );
263
    }
264
265
    public function testFetchAssoc()
266
    {
267
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
268
        $row = $this->_conn->fetchAssoc($sql, array(1, 'foo'));
269
270
        self::assertNotFalse($row);
271
272
        $row = array_change_key_case($row, \CASE_LOWER);
273
274
        self::assertEquals(1, $row['test_int']);
275
        self::assertEquals('foo', $row['test_string']);
276
    }
277
278
    public function testFetchAssocWithTypes()
279
    {
280
        $datetimeString = '2010-01-01 10:10:10';
281
        $datetime = new \DateTime($datetimeString);
282
283
        $sql = 'SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?';
284
        $row = $this->_conn->fetchAssoc($sql, [1, $datetime], [ParameterType::STRING, Type::DATETIME]);
285
286
        self::assertNotFalse($row);
287
288
        $row = array_change_key_case($row, \CASE_LOWER);
289
290
        self::assertEquals(1, $row['test_int']);
291
        self::assertStringStartsWith($datetimeString, $row['test_datetime']);
292
    }
293
294
    /**
295
     * @expectedException \Doctrine\DBAL\DBALException
296
     */
297
    public function testFetchAssocWithMissingTypes()
298
    {
299
        if ($this->_conn->getDriver() instanceof \Doctrine\DBAL\Driver\Mysqli\Driver ||
300
            $this->_conn->getDriver() instanceof \Doctrine\DBAL\Driver\SQLSrv\Driver) {
301
            $this->markTestSkipped('mysqli and sqlsrv actually supports this');
302
        }
303
304
        $datetimeString = '2010-01-01 10:10:10';
305
        $datetime = new \DateTime($datetimeString);
306
        $sql = "SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?";
307
        $row = $this->_conn->fetchAssoc($sql, array(1, $datetime));
308
    }
309
310
    public function testFetchArray()
311
    {
312
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
313
        $row = $this->_conn->fetchArray($sql, array(1, 'foo'));
314
315
        self::assertEquals(1, $row[0]);
316
        self::assertEquals('foo', $row[1]);
317
    }
318
319
    public function testFetchArrayWithTypes()
320
    {
321
        $datetimeString = '2010-01-01 10:10:10';
322
        $datetime = new \DateTime($datetimeString);
323
324
        $sql = 'SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?';
325
        $row = $this->_conn->fetchArray($sql, [1, $datetime], [ParameterType::STRING, Type::DATETIME]);
326
327
        self::assertNotFalse($row);
328
329
        $row = array_change_key_case($row, \CASE_LOWER);
330
331
        self::assertEquals(1, $row[0]);
332
        self::assertStringStartsWith($datetimeString, $row[1]);
333
    }
334
335
    /**
336
     * @expectedException \Doctrine\DBAL\DBALException
337
     */
338
    public function testFetchArrayWithMissingTypes()
339
    {
340
        if ($this->_conn->getDriver() instanceof \Doctrine\DBAL\Driver\Mysqli\Driver ||
341
            $this->_conn->getDriver() instanceof \Doctrine\DBAL\Driver\SQLSrv\Driver) {
342
            $this->markTestSkipped('mysqli and sqlsrv actually supports this');
343
        }
344
345
        $datetimeString = '2010-01-01 10:10:10';
346
        $datetime = new \DateTime($datetimeString);
347
        $sql = "SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?";
348
        $row = $this->_conn->fetchArray($sql, array(1, $datetime));
349
    }
350
351
    public function testFetchColumn()
352
    {
353
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
354
        $testInt = $this->_conn->fetchColumn($sql, array(1, 'foo'), 0);
355
356
        self::assertEquals(1, $testInt);
357
358
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
359
        $testString = $this->_conn->fetchColumn($sql, array(1, 'foo'), 1);
360
361
        self::assertEquals('foo', $testString);
362
    }
363
364
    public function testFetchColumnWithTypes()
365
    {
366
        $datetimeString = '2010-01-01 10:10:10';
367
        $datetime = new \DateTime($datetimeString);
368
369
        $sql    = 'SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?';
370
        $column = $this->_conn->fetchColumn($sql, [1, $datetime], 1, [ParameterType::STRING, Type::DATETIME]);
371
372
        self::assertNotFalse($column);
373
374
        self::assertStringStartsWith($datetimeString, $column);
375
    }
376
377
    /**
378
     * @expectedException \Doctrine\DBAL\DBALException
379
     */
380
    public function testFetchColumnWithMissingTypes()
381
    {
382
        if ($this->_conn->getDriver() instanceof \Doctrine\DBAL\Driver\Mysqli\Driver ||
383
            $this->_conn->getDriver() instanceof \Doctrine\DBAL\Driver\SQLSrv\Driver) {
384
            $this->markTestSkipped('mysqli and sqlsrv actually supports this');
385
        }
386
387
        $datetimeString = '2010-01-01 10:10:10';
388
        $datetime = new \DateTime($datetimeString);
389
        $sql = "SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?";
390
        $column = $this->_conn->fetchColumn($sql, array(1, $datetime), 1);
391
    }
392
393
    /**
394
     * @group DDC-697
395
     */
396
    public function testExecuteQueryBindDateTimeType()
397
    {
398
        $sql = 'SELECT count(*) AS c FROM fetch_table WHERE test_datetime = ?';
399
        $stmt = $this->_conn->executeQuery($sql,
400
            array(1 => new \DateTime('2010-01-01 10:10:10')),
401
            array(1 => Type::DATETIME)
402
        );
403
404
        self::assertEquals(1, $stmt->fetchColumn());
405
    }
406
407
    /**
408
     * @group DDC-697
409
     */
410
    public function testExecuteUpdateBindDateTimeType()
411
    {
412
        $datetime = new \DateTime('2010-02-02 20:20:20');
413
414
        $sql = 'INSERT INTO fetch_table (test_int, test_string, test_datetime) VALUES (?, ?, ?)';
415
        $affectedRows = $this->_conn->executeUpdate($sql, [
416
            1 => 50,
417
            2 => 'foo',
418
            3 => $datetime,
419
        ], [
420
            1 => ParameterType::INTEGER,
421
            2 => ParameterType::STRING,
422
            3 => Type::DATETIME,
423
        ]);
424
425
        self::assertEquals(1, $affectedRows);
426
        self::assertEquals(1, $this->_conn->executeQuery(
427
            'SELECT count(*) AS c FROM fetch_table WHERE test_datetime = ?',
428
            array(1 => $datetime),
429
            array(1 => Type::DATETIME)
430
        )->fetchColumn());
431
    }
432
433
    /**
434
     * @group DDC-697
435
     */
436
    public function testPrepareQueryBindValueDateTimeType()
437
    {
438
        $sql = 'SELECT count(*) AS c FROM fetch_table WHERE test_datetime = ?';
439
        $stmt = $this->_conn->prepare($sql);
440
        $stmt->bindValue(1, new \DateTime('2010-01-01 10:10:10'), Type::DATETIME);
441
        $stmt->execute();
442
443
        self::assertEquals(1, $stmt->fetchColumn());
444
    }
445
446
    /**
447
     * @group DBAL-78
448
     */
449
    public function testNativeArrayListSupport()
450
    {
451
        for ($i = 100; $i < 110; $i++) {
452
            $this->_conn->insert('fetch_table', array('test_int' => $i, 'test_string' => 'foo' . $i, 'test_datetime' => '2010-01-01 10:10:10'));
453
        }
454
455
        $stmt = $this->_conn->executeQuery('SELECT test_int FROM fetch_table WHERE test_int IN (?)',
456
            array(array(100, 101, 102, 103, 104)), array(Connection::PARAM_INT_ARRAY));
457
458
        $data = $stmt->fetchAll(FetchMode::NUMERIC);
459
        self::assertCount(5, $data);
460
        self::assertEquals(array(array(100), array(101), array(102), array(103), array(104)), $data);
461
462
        $stmt = $this->_conn->executeQuery('SELECT test_int FROM fetch_table WHERE test_string IN (?)',
463
            array(array('foo100', 'foo101', 'foo102', 'foo103', 'foo104')), array(Connection::PARAM_STR_ARRAY));
464
465
        $data = $stmt->fetchAll(FetchMode::NUMERIC);
466
        self::assertCount(5, $data);
467
        self::assertEquals(array(array(100), array(101), array(102), array(103), array(104)), $data);
468
    }
469
470
    /**
471
     * @dataProvider getTrimExpressionData
472
     */
473
    public function testTrimExpression($value, $position, $char, $expectedResult)
474
    {
475
        $sql = 'SELECT ' .
476
            $this->_conn->getDatabasePlatform()->getTrimExpression($value, $position, $char) . ' AS trimmed ' .
477
            'FROM fetch_table';
478
479
        $row = $this->_conn->fetchAssoc($sql);
480
        $row = array_change_key_case($row, CASE_LOWER);
481
482
        self::assertEquals($expectedResult, $row['trimmed']);
483
    }
484
485
    public function getTrimExpressionData()
486
    {
487
        return array(
488
            ['test_string', TrimMode::UNSPECIFIED, false, 'foo'],
489
            ['test_string', TrimMode::LEADING, false, 'foo'],
490
            ['test_string', TrimMode::TRAILING, false, 'foo'],
491
            ['test_string', TrimMode::BOTH, false, 'foo'],
492
            ['test_string', TrimMode::UNSPECIFIED, "'f'", 'oo'],
493
            ['test_string', TrimMode::UNSPECIFIED, "'o'", 'f'],
494
            ['test_string', TrimMode::UNSPECIFIED, "'.'", 'foo'],
495
            ['test_string', TrimMode::LEADING, "'f'", 'oo'],
496
            ['test_string', TrimMode::LEADING, "'o'", 'foo'],
497
            ['test_string', TrimMode::LEADING, "'.'", 'foo'],
498
            ['test_string', TrimMode::TRAILING, "'f'", 'foo'],
499
            ['test_string', TrimMode::TRAILING, "'o'", 'f'],
500
            ['test_string', TrimMode::TRAILING, "'.'", 'foo'],
501
            ['test_string', TrimMode::BOTH, "'f'", 'oo'],
502
            ['test_string', TrimMode::BOTH, "'o'", 'f'],
503
            ['test_string', TrimMode::BOTH, "'.'", 'foo'],
504
            ["' foo '", TrimMode::UNSPECIFIED, false, 'foo'],
505
            ["' foo '", TrimMode::LEADING, false, 'foo '],
506
            ["' foo '", TrimMode::TRAILING, false, ' foo'],
507
            ["' foo '", TrimMode::BOTH, false, 'foo'],
508
            ["' foo '", TrimMode::UNSPECIFIED, "'f'", ' foo '],
509
            ["' foo '", TrimMode::UNSPECIFIED, "'o'", ' foo '],
510
            ["' foo '", TrimMode::UNSPECIFIED, "'.'", ' foo '],
511
            ["' foo '", TrimMode::UNSPECIFIED, "' '", 'foo'],
512
            ["' foo '", TrimMode::LEADING, "'f'", ' foo '],
513
            ["' foo '", TrimMode::LEADING, "'o'", ' foo '],
514
            ["' foo '", TrimMode::LEADING, "'.'", ' foo '],
515
            ["' foo '", TrimMode::LEADING, "' '", 'foo '],
516
            ["' foo '", TrimMode::TRAILING, "'f'", ' foo '],
517
            ["' foo '", TrimMode::TRAILING, "'o'", ' foo '],
518
            ["' foo '", TrimMode::TRAILING, "'.'", ' foo '],
519
            ["' foo '", TrimMode::TRAILING, "' '", ' foo'],
520
            ["' foo '", TrimMode::BOTH, "'f'", ' foo '],
521
            ["' foo '", TrimMode::BOTH, "'o'", ' foo '],
522
            ["' foo '", TrimMode::BOTH, "'.'", ' foo '],
523
            ["' foo '", TrimMode::BOTH, "' '", 'foo'],
524
        );
525
    }
526
527
    /**
528
     * @group DDC-1014
529
     */
530
    public function testDateArithmetics()
531
    {
532
        $p = $this->_conn->getDatabasePlatform();
533
        $sql = 'SELECT ';
534
        $sql .= $p->getDateDiffExpression('test_datetime', $p->getCurrentTimestampSQL()) .' AS diff, ';
535
        $sql .= $p->getDateAddSecondsExpression('test_datetime', 1) .' AS add_seconds, ';
536
        $sql .= $p->getDateSubSecondsExpression('test_datetime', 1) .' AS sub_seconds, ';
537
        $sql .= $p->getDateAddMinutesExpression('test_datetime', 5) .' AS add_minutes, ';
538
        $sql .= $p->getDateSubMinutesExpression('test_datetime', 5) .' AS sub_minutes, ';
539
        $sql .= $p->getDateAddHourExpression('test_datetime', 3) .' AS add_hour, ';
540
        $sql .= $p->getDateSubHourExpression('test_datetime', 3) .' AS sub_hour, ';
541
        $sql .= $p->getDateAddDaysExpression('test_datetime', 10) .' AS add_days, ';
542
        $sql .= $p->getDateSubDaysExpression('test_datetime', 10) .' AS sub_days, ';
543
        $sql .= $p->getDateAddWeeksExpression('test_datetime', 1) .' AS add_weeks, ';
544
        $sql .= $p->getDateSubWeeksExpression('test_datetime', 1) .' AS sub_weeks, ';
545
        $sql .= $p->getDateAddMonthExpression('test_datetime', 2) .' AS add_month, ';
546
        $sql .= $p->getDateSubMonthExpression('test_datetime', 2) .' AS sub_month, ';
547
        $sql .= $p->getDateAddQuartersExpression('test_datetime', 3) .' AS add_quarters, ';
548
        $sql .= $p->getDateSubQuartersExpression('test_datetime', 3) .' AS sub_quarters, ';
549
        $sql .= $p->getDateAddYearsExpression('test_datetime', 6) .' AS add_years, ';
550
        $sql .= $p->getDateSubYearsExpression('test_datetime', 6) .' AS sub_years ';
551
        $sql .= 'FROM fetch_table';
552
553
        $row = $this->_conn->fetchAssoc($sql);
554
        $row = array_change_key_case($row, CASE_LOWER);
555
556
        $diff = (strtotime('2010-01-01') - strtotime(date('Y-m-d'))) / 3600 / 24;
557
        self::assertEquals($diff, $row['diff'], "Date difference should be approx. ".$diff." days.", 1);
558
        self::assertEquals('2010-01-01 10:10:11', date('Y-m-d H:i:s', strtotime($row['add_seconds'])), "Adding second should end up on 2010-01-01 10:10:11");
559
        self::assertEquals('2010-01-01 10:10:09', date('Y-m-d H:i:s', strtotime($row['sub_seconds'])), "Subtracting second should end up on 2010-01-01 10:10:09");
560
        self::assertEquals('2010-01-01 10:15:10', date('Y-m-d H:i:s', strtotime($row['add_minutes'])), "Adding minutes should end up on 2010-01-01 10:15:10");
561
        self::assertEquals('2010-01-01 10:05:10', date('Y-m-d H:i:s', strtotime($row['sub_minutes'])), "Subtracting minutes should end up on 2010-01-01 10:05:10");
562
        self::assertEquals('2010-01-01 13:10', date('Y-m-d H:i', strtotime($row['add_hour'])), "Adding date should end up on 2010-01-01 13:10");
563
        self::assertEquals('2010-01-01 07:10', date('Y-m-d H:i', strtotime($row['sub_hour'])), "Subtracting date should end up on 2010-01-01 07:10");
564
        self::assertEquals('2010-01-11', date('Y-m-d', strtotime($row['add_days'])), "Adding date should end up on 2010-01-11");
565
        self::assertEquals('2009-12-22', date('Y-m-d', strtotime($row['sub_days'])), "Subtracting date should end up on 2009-12-22");
566
        self::assertEquals('2010-01-08', date('Y-m-d', strtotime($row['add_weeks'])), "Adding week should end up on 2010-01-08");
567
        self::assertEquals('2009-12-25', date('Y-m-d', strtotime($row['sub_weeks'])), "Subtracting week should end up on 2009-12-25");
568
        self::assertEquals('2010-03-01', date('Y-m-d', strtotime($row['add_month'])), "Adding month should end up on 2010-03-01");
569
        self::assertEquals('2009-11-01', date('Y-m-d', strtotime($row['sub_month'])), "Subtracting month should end up on 2009-11-01");
570
        self::assertEquals('2010-10-01', date('Y-m-d', strtotime($row['add_quarters'])), "Adding quarters should end up on 2010-04-01");
571
        self::assertEquals('2009-04-01', date('Y-m-d', strtotime($row['sub_quarters'])), "Subtracting quarters should end up on 2009-10-01");
572
        self::assertEquals('2016-01-01', date('Y-m-d', strtotime($row['add_years'])), "Adding years should end up on 2016-01-01");
573
        self::assertEquals('2004-01-01', date('Y-m-d', strtotime($row['sub_years'])), "Subtracting years should end up on 2004-01-01");
574
    }
575
576
    public function testLocateExpression()
577
    {
578
        $platform = $this->_conn->getDatabasePlatform();
579
580
        $sql = 'SELECT ';
581
        $sql .= $platform->getLocateExpression('test_string', "'oo'") .' AS locate1, ';
582
        $sql .= $platform->getLocateExpression('test_string', "'foo'") .' AS locate2, ';
583
        $sql .= $platform->getLocateExpression('test_string', "'bar'") .' AS locate3, ';
584
        $sql .= $platform->getLocateExpression('test_string', 'test_string') .' AS locate4, ';
585
        $sql .= $platform->getLocateExpression("'foo'", 'test_string') .' AS locate5, ';
586
        $sql .= $platform->getLocateExpression("'barfoobaz'", 'test_string') .' AS locate6, ';
587
        $sql .= $platform->getLocateExpression("'bar'", 'test_string') .' AS locate7, ';
588
        $sql .= $platform->getLocateExpression('test_string', "'oo'", 2) .' AS locate8, ';
589
        $sql .= $platform->getLocateExpression('test_string', "'oo'", 3) .' AS locate9 ';
590
        $sql .= 'FROM fetch_table';
591
592
        $row = $this->_conn->fetchAssoc($sql);
593
        $row = array_change_key_case($row, CASE_LOWER);
594
595
        self::assertEquals(2, $row['locate1']);
596
        self::assertEquals(1, $row['locate2']);
597
        self::assertEquals(0, $row['locate3']);
598
        self::assertEquals(1, $row['locate4']);
599
        self::assertEquals(1, $row['locate5']);
600
        self::assertEquals(4, $row['locate6']);
601
        self::assertEquals(0, $row['locate7']);
602
        self::assertEquals(2, $row['locate8']);
603
        self::assertEquals(0, $row['locate9']);
604
    }
605
606
    public function testQuoteSQLInjection()
607
    {
608
        $sql = "SELECT * FROM fetch_table WHERE test_string = " . $this->_conn->quote("bar' OR '1'='1");
609
        $rows = $this->_conn->fetchAll($sql);
610
611
        self::assertCount(0, $rows, "no result should be returned, otherwise SQL injection is possible");
612
    }
613
614
    /**
615
     * @group DDC-1213
616
     */
617
    public function testBitComparisonExpressionSupport()
618
    {
619
        $this->_conn->exec('DELETE FROM fetch_table');
620
        $platform = $this->_conn->getDatabasePlatform();
621
        $bitmap   = array();
622
623
        for ($i = 2; $i < 9; $i = $i + 2) {
624
            $bitmap[$i] = array(
625
                'bit_or'    => ($i | 2),
626
                'bit_and'   => ($i & 2)
627
            );
628
            $this->_conn->insert('fetch_table', array(
629
                'test_int'      => $i,
630
                'test_string'   => json_encode($bitmap[$i]),
631
                'test_datetime' => '2010-01-01 10:10:10'
632
            ));
633
        }
634
635
        $sql[]  = 'SELECT ';
636
        $sql[]  = 'test_int, ';
637
        $sql[]  = 'test_string, ';
638
        $sql[]  = $platform->getBitOrComparisonExpression('test_int', 2) . ' AS bit_or, ';
639
        $sql[]  = $platform->getBitAndComparisonExpression('test_int', 2) . ' AS bit_and ';
640
        $sql[]  = 'FROM fetch_table';
641
642
        $stmt = $this->_conn->executeQuery(implode(PHP_EOL, $sql));
643
        $data = $stmt->fetchAll(FetchMode::ASSOCIATIVE);
644
645
646
        self::assertCount(4, $data);
647
        self::assertEquals(count($bitmap), count($data));
648
        foreach ($data as $row) {
649
            $row = array_change_key_case($row, CASE_LOWER);
650
651
            self::assertArrayHasKey('test_int', $row);
652
653
            $id = $row['test_int'];
654
655
            self::assertArrayHasKey($id, $bitmap);
656
            self::assertArrayHasKey($id, $bitmap);
657
658
            self::assertArrayHasKey('bit_or', $row);
659
            self::assertArrayHasKey('bit_and', $row);
660
661
            self::assertEquals($row['bit_or'], $bitmap[$id]['bit_or']);
662
            self::assertEquals($row['bit_and'], $bitmap[$id]['bit_and']);
663
        }
664
    }
665
666
    public function testSetDefaultFetchMode()
667
    {
668
        $stmt = $this->_conn->query("SELECT * FROM fetch_table");
669
        $stmt->setFetchMode(FetchMode::NUMERIC);
670
671
        $row = array_keys($stmt->fetch());
672
        self::assertCount(0, array_filter($row, function($v) { return ! is_numeric($v); }), "should be no non-numerical elements in the result.");
673
    }
674
675
    /**
676
     * @group DBAL-1091
677
     */
678
    public function testFetchAllStyleObject()
679
    {
680
        $this->setupFixture();
681
682
        $sql = 'SELECT test_int, test_string, test_datetime FROM fetch_table';
683
        $stmt = $this->_conn->prepare($sql);
684
685
        $stmt->execute();
686
687
        $results = $stmt->fetchAll(FetchMode::STANDARD_OBJECT);
688
689
        self::assertCount(1, $results);
690
        self::assertInstanceOf('stdClass', $results[0]);
691
692
        self::assertEquals(
693
            1,
694
            property_exists($results[0], 'test_int') ? $results[0]->test_int : $results[0]->TEST_INT
695
        );
696
        self::assertEquals(
697
            'foo',
698
            property_exists($results[0], 'test_string') ? $results[0]->test_string : $results[0]->TEST_STRING
699
        );
700
        self::assertStringStartsWith(
701
            '2010-01-01 10:10:10',
702
            property_exists($results[0], 'test_datetime') ? $results[0]->test_datetime : $results[0]->TEST_DATETIME
703
        );
704
    }
705
706
    /**
707
     * @group DBAL-196
708
     */
709
    public function testFetchAllSupportFetchClass()
710
    {
711
        $this->skipOci8AndMysqli();
712
        $this->setupFixture();
713
714
        $sql    = "SELECT test_int, test_string, test_datetime FROM fetch_table";
715
        $stmt   = $this->_conn->prepare($sql);
716
        $stmt->execute();
717
718
        $results = $stmt->fetchAll(
719
            FetchMode::CUSTOM_OBJECT,
720
            __NAMESPACE__.'\\MyFetchClass'
721
        );
722
723
        self::assertCount(1, $results);
724
        self::assertInstanceOf(__NAMESPACE__.'\\MyFetchClass', $results[0]);
725
726
        self::assertEquals(1, $results[0]->test_int);
727
        self::assertEquals('foo', $results[0]->test_string);
728
        self::assertStringStartsWith('2010-01-01 10:10:10', $results[0]->test_datetime);
729
    }
730
731
    /**
732
     * @group DBAL-241
733
     */
734
    public function testFetchAllStyleColumn()
735
    {
736
        $sql = "DELETE FROM fetch_table";
737
        $this->_conn->executeUpdate($sql);
738
739
        $this->_conn->insert('fetch_table', array('test_int' => 1, 'test_string' => 'foo'));
740
        $this->_conn->insert('fetch_table', array('test_int' => 10, 'test_string' => 'foo'));
741
742
        $sql = "SELECT test_int FROM fetch_table";
743
        $rows = $this->_conn->query($sql)->fetchAll(FetchMode::COLUMN);
744
745
        self::assertEquals(array(1, 10), $rows);
746
    }
747
748
    /**
749
     * @group DBAL-214
750
     */
751
    public function testSetFetchModeClassFetchAll()
752
    {
753
        $this->skipOci8AndMysqli();
754
        $this->setupFixture();
755
756
        $sql = "SELECT * FROM fetch_table";
757
        $stmt = $this->_conn->query($sql);
758
        $stmt->setFetchMode(FetchMode::CUSTOM_OBJECT, __NAMESPACE__ . '\\MyFetchClass');
759
760
        $results = $stmt->fetchAll();
761
762
        self::assertCount(1, $results);
763
        self::assertInstanceOf(__NAMESPACE__.'\\MyFetchClass', $results[0]);
764
765
        self::assertEquals(1, $results[0]->test_int);
766
        self::assertEquals('foo', $results[0]->test_string);
767
        self::assertStringStartsWith('2010-01-01 10:10:10', $results[0]->test_datetime);
768
    }
769
770
    /**
771
     * @group DBAL-214
772
     */
773
    public function testSetFetchModeClassFetch()
774
    {
775
        $this->skipOci8AndMysqli();
776
        $this->setupFixture();
777
778
        $sql = "SELECT * FROM fetch_table";
779
        $stmt = $this->_conn->query($sql);
780
        $stmt->setFetchMode(FetchMode::CUSTOM_OBJECT, __NAMESPACE__ . '\\MyFetchClass');
781
782
        $results = array();
783
        while ($row = $stmt->fetch()) {
784
            $results[] = $row;
785
        }
786
787
        self::assertCount(1, $results);
788
        self::assertInstanceOf(__NAMESPACE__.'\\MyFetchClass', $results[0]);
789
790
        self::assertEquals(1, $results[0]->test_int);
791
        self::assertEquals('foo', $results[0]->test_string);
792
        self::assertStringStartsWith('2010-01-01 10:10:10', $results[0]->test_datetime);
793
    }
794
795
    /**
796
     * @group DBAL-257
797
     */
798
    public function testEmptyFetchColumnReturnsFalse()
799
    {
800
        $this->_conn->beginTransaction();
801
        $this->_conn->exec('DELETE FROM fetch_table');
802
        self::assertFalse($this->_conn->fetchColumn('SELECT test_int FROM fetch_table'));
803
        self::assertFalse($this->_conn->query('SELECT test_int FROM fetch_table')->fetchColumn());
804
        $this->_conn->rollBack();
805
    }
806
807
    /**
808
     * @group DBAL-339
809
     */
810
    public function testSetFetchModeOnDbalStatement()
811
    {
812
        $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?";
813
        $stmt = $this->_conn->executeQuery($sql, array(1, "foo"));
814
        $stmt->setFetchMode(FetchMode::NUMERIC);
815
816
        $row = $stmt->fetch();
817
818
        self::assertArrayHasKey(0, $row);
819
        self::assertArrayHasKey(1, $row);
820
        self::assertFalse($stmt->fetch());
821
    }
822
823
    /**
824
     * @group DBAL-435
825
     */
826
    public function testEmptyParameters()
827
    {
828
        $sql = "SELECT * FROM fetch_table WHERE test_int IN (?)";
829
        $stmt = $this->_conn->executeQuery($sql, array(array()), array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY));
830
        $rows = $stmt->fetchAll();
831
832
        self::assertEquals(array(), $rows);
833
    }
834
835
    /**
836
     * @group DBAL-1028
837
     */
838
    public function testFetchColumnNullValue()
839
    {
840
        $this->_conn->executeUpdate(
841
            'INSERT INTO fetch_table (test_int, test_string) VALUES (?, ?)',
842
            array(2, 'foo')
843
        );
844
845
        self::assertNull(
846
            $this->_conn->fetchColumn('SELECT test_datetime FROM fetch_table WHERE test_int = ?', array(2))
847
        );
848
    }
849
850
    /**
851
     * @group DBAL-1028
852
     */
853
    public function testFetchColumnNonExistingIndex()
854
    {
855
        if ($this->_conn->getDriver()->getName() === 'pdo_sqlsrv') {
856
            $this->markTestSkipped(
857
                'Test does not work for pdo_sqlsrv driver as it throws a fatal error for a non-existing column index.'
858
            );
859
        }
860
861
        self::assertNull(
862
            $this->_conn->fetchColumn('SELECT test_int FROM fetch_table WHERE test_int = ?', array(1), 1)
863
        );
864
    }
865
866
    /**
867
     * @group DBAL-1028
868
     */
869
    public function testFetchColumnNoResult()
870
    {
871
        self::assertFalse(
872
            $this->_conn->fetchColumn('SELECT test_int FROM fetch_table WHERE test_int = ?', array(-1))
873
        );
874
    }
875
876
    private function setupFixture()
877
    {
878
        $this->_conn->exec('DELETE FROM fetch_table');
879
        $this->_conn->insert('fetch_table', array(
880
            'test_int'      => 1,
881
            'test_string'   => 'foo',
882
            'test_datetime' => '2010-01-01 10:10:10'
883
        ));
884
    }
885
886
    private function skipOci8AndMysqli()
887
    {
888
        if (isset($GLOBALS['db_type']) && $GLOBALS['db_type'] == "oci8")  {
889
            $this->markTestSkipped("Not supported by OCI8");
890
        }
891
        if ('mysqli' == $this->_conn->getDriver()->getName()) {
892
            $this->markTestSkipped('Mysqli driver dont support this feature.');
893
        }
894
    }
895
}
896
897
class MyFetchClass
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
898
{
899
    public $test_int, $test_string, $test_datetime;
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
900
}
901