QueryDqlFunctionTest   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 428
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 246
c 2
b 0
f 0
dl 0
loc 428
rs 10
wmc 28

28 Methods

Rating   Name   Duplication   Size   Complexity  
A generateFixture() 0 32 1
A testBitAndComparison() 0 19 1
A testBitOrComparison() 0 19 1
A testFunctionLower() 0 10 1
A testAggregateCount() 0 6 1
A testConcatFunction() 0 10 1
A testAggregateAvg() 0 6 1
A testOperatorDiv() 0 10 1
A testAggregateSum() 0 6 1
A testFunctionTrim() 0 21 1
A testOperatorSub() 0 10 1
A testFunctionAbs() 0 10 1
A testFunctionSqrt() 0 10 1
A testOperatorAdd() 0 10 1
A testAggregateMin() 0 6 1
A testDateDiff() 0 11 1
A testAggregateMax() 0 6 1
A testFunctionMod() 0 10 1
A testFunctionUpper() 0 10 1
A setUp() 0 6 1
A testFunctionConcat() 0 10 1
A testOperatorMultiply() 0 10 1
A testFunctionSubstring() 0 18 1
A testFunctionLength() 0 10 1
A testFunctionLocate() 0 17 1
A dateAddSubProvider() 0 12 1
A testDateSub() 0 21 1
A testDateAdd() 0 21 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\ORM\Functional;
6
7
use DateTimeImmutable;
8
use Doctrine\ORM\AbstractQuery;
9
use Doctrine\Tests\Models\Company\CompanyManager;
10
use Doctrine\Tests\OrmFunctionalTestCase;
11
use function round;
12
use function sprintf;
13
14
/**
15
 * Functional Query tests.
16
 */
17
class QueryDqlFunctionTest extends OrmFunctionalTestCase
18
{
19
    protected function setUp() : void
20
    {
21
        $this->useModelSet('company');
22
        parent::setUp();
23
24
        $this->generateFixture();
25
    }
26
27
    public function testAggregateSum() : void
28
    {
29
        $salarySum = $this->em->createQuery('SELECT SUM(m.salary) AS salary FROM Doctrine\Tests\Models\Company\CompanyManager m')
30
                               ->getSingleResult();
31
32
        self::assertEquals(1500000, $salarySum['salary']);
33
    }
34
35
    public function testAggregateAvg() : void
36
    {
37
        $salaryAvg = $this->em->createQuery('SELECT AVG(m.salary) AS salary FROM Doctrine\Tests\Models\Company\CompanyManager m')
38
                               ->getSingleResult();
39
40
        self::assertEquals(375000, round($salaryAvg['salary'], 0));
41
    }
42
43
    public function testAggregateMin() : void
44
    {
45
        $salary = $this->em->createQuery('SELECT MIN(m.salary) AS salary FROM Doctrine\Tests\Models\Company\CompanyManager m')
46
                               ->getSingleResult();
47
48
        self::assertEquals(100000, $salary['salary']);
49
    }
50
51
    public function testAggregateMax() : void
52
    {
53
        $salary = $this->em->createQuery('SELECT MAX(m.salary) AS salary FROM Doctrine\Tests\Models\Company\CompanyManager m')
54
                               ->getSingleResult();
55
56
        self::assertEquals(800000, $salary['salary']);
57
    }
58
59
    public function testAggregateCount() : void
60
    {
61
        $managerCount = $this->em->createQuery('SELECT COUNT(m.id) AS managers FROM Doctrine\Tests\Models\Company\CompanyManager m')
62
                               ->getSingleResult();
63
64
        self::assertEquals(4, $managerCount['managers']);
65
    }
66
67
    public function testFunctionAbs() : void
68
    {
69
        $result = $this->em->createQuery('SELECT m, ABS(m.salary * -1) AS abs FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
70
                         ->getResult();
71
72
        self::assertCount(4, $result);
73
        self::assertEquals(100000, $result[0]['abs']);
74
        self::assertEquals(200000, $result[1]['abs']);
75
        self::assertEquals(400000, $result[2]['abs']);
76
        self::assertEquals(800000, $result[3]['abs']);
77
    }
78
79
    public function testFunctionConcat() : void
80
    {
81
        $arg = $this->em->createQuery('SELECT m, CONCAT(m.name, m.department) AS namedep FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
82
                         ->getArrayResult();
83
84
        self::assertCount(4, $arg);
85
        self::assertEquals('Roman B.IT', $arg[0]['namedep']);
86
        self::assertEquals('Benjamin E.HR', $arg[1]['namedep']);
87
        self::assertEquals('Guilherme B.Complaint Department', $arg[2]['namedep']);
88
        self::assertEquals('Jonathan W.Administration', $arg[3]['namedep']);
89
    }
90
91
    public function testFunctionLength() : void
92
    {
93
        $result = $this->em->createQuery('SELECT m, LENGTH(CONCAT(m.name, m.department)) AS namedeplength FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
94
                         ->getArrayResult();
95
96
        self::assertCount(4, $result);
97
        self::assertEquals(10, $result[0]['namedeplength']);
98
        self::assertEquals(13, $result[1]['namedeplength']);
99
        self::assertEquals(32, $result[2]['namedeplength']);
100
        self::assertEquals(25, $result[3]['namedeplength']);
101
    }
102
103
    public function testFunctionLocate() : void
104
    {
105
        $dql = "SELECT m, LOCATE('e', LOWER(m.name)) AS loc, LOCATE('e', LOWER(m.name), 7) AS loc2 " .
106
               'FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC';
107
108
        $result = $this->em->createQuery($dql)
109
                         ->getArrayResult();
110
111
        self::assertCount(4, $result);
112
        self::assertEquals(0, $result[0]['loc']);
113
        self::assertEquals(2, $result[1]['loc']);
114
        self::assertEquals(6, $result[2]['loc']);
115
        self::assertEquals(0, $result[3]['loc']);
116
        self::assertEquals(0, $result[0]['loc2']);
117
        self::assertEquals(10, $result[1]['loc2']);
118
        self::assertEquals(9, $result[2]['loc2']);
119
        self::assertEquals(0, $result[3]['loc2']);
120
    }
121
122
    public function testFunctionLower() : void
123
    {
124
        $result = $this->em->createQuery('SELECT m, LOWER(m.name) AS lowername FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
125
                         ->getArrayResult();
126
127
        self::assertCount(4, $result);
128
        self::assertEquals('roman b.', $result[0]['lowername']);
129
        self::assertEquals('benjamin e.', $result[1]['lowername']);
130
        self::assertEquals('guilherme b.', $result[2]['lowername']);
131
        self::assertEquals('jonathan w.', $result[3]['lowername']);
132
    }
133
134
    public function testFunctionMod() : void
135
    {
136
        $result = $this->em->createQuery('SELECT m, MOD(m.salary, 3500) AS amod FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
137
                         ->getArrayResult();
138
139
        self::assertCount(4, $result);
140
        self::assertEquals(2000, $result[0]['amod']);
141
        self::assertEquals(500, $result[1]['amod']);
142
        self::assertEquals(1000, $result[2]['amod']);
143
        self::assertEquals(2000, $result[3]['amod']);
144
    }
145
146
    public function testFunctionSqrt() : void
147
    {
148
        $result = $this->em->createQuery('SELECT m, SQRT(m.salary) AS sqrtsalary FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
149
                         ->getArrayResult();
150
151
        self::assertCount(4, $result);
152
        self::assertEquals(316, round($result[0]['sqrtsalary']));
153
        self::assertEquals(447, round($result[1]['sqrtsalary']));
154
        self::assertEquals(632, round($result[2]['sqrtsalary']));
155
        self::assertEquals(894, round($result[3]['sqrtsalary']));
156
    }
157
158
    public function testFunctionUpper() : void
159
    {
160
        $result = $this->em->createQuery('SELECT m, UPPER(m.name) AS uppername FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
161
                         ->getArrayResult();
162
163
        self::assertCount(4, $result);
164
        self::assertEquals('ROMAN B.', $result[0]['uppername']);
165
        self::assertEquals('BENJAMIN E.', $result[1]['uppername']);
166
        self::assertEquals('GUILHERME B.', $result[2]['uppername']);
167
        self::assertEquals('JONATHAN W.', $result[3]['uppername']);
168
    }
169
170
    public function testFunctionSubstring() : void
171
    {
172
        $dql = 'SELECT m, SUBSTRING(m.name, 1, 3) AS str1, SUBSTRING(m.name, 5) AS str2 ' .
173
                'FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.name';
174
175
        $result = $this->em->createQuery($dql)
176
                         ->getArrayResult();
177
178
        self::assertCount(4, $result);
179
        self::assertEquals('Ben', $result[0]['str1']);
180
        self::assertEquals('Gui', $result[1]['str1']);
181
        self::assertEquals('Jon', $result[2]['str1']);
182
        self::assertEquals('Rom', $result[3]['str1']);
183
184
        self::assertEquals('amin E.', $result[0]['str2']);
185
        self::assertEquals('herme B.', $result[1]['str2']);
186
        self::assertEquals('than W.', $result[2]['str2']);
187
        self::assertEquals('n B.', $result[3]['str2']);
188
    }
189
190
    public function testFunctionTrim() : void
191
    {
192
        $dql = "SELECT m, TRIM(TRAILING '.' FROM m.name) AS str1, " .
193
               " TRIM(LEADING '.' FROM m.name) AS str2, TRIM(CONCAT(' ', CONCAT(m.name, ' '))) AS str3 " .
194
               'FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC';
195
196
        $result = $this->em->createQuery($dql)->getArrayResult();
197
198
        self::assertCount(4, $result);
199
        self::assertEquals('Roman B', $result[0]['str1']);
200
        self::assertEquals('Benjamin E', $result[1]['str1']);
201
        self::assertEquals('Guilherme B', $result[2]['str1']);
202
        self::assertEquals('Jonathan W', $result[3]['str1']);
203
        self::assertEquals('Roman B.', $result[0]['str2']);
204
        self::assertEquals('Benjamin E.', $result[1]['str2']);
205
        self::assertEquals('Guilherme B.', $result[2]['str2']);
206
        self::assertEquals('Jonathan W.', $result[3]['str2']);
207
        self::assertEquals('Roman B.', $result[0]['str3']);
208
        self::assertEquals('Benjamin E.', $result[1]['str3']);
209
        self::assertEquals('Guilherme B.', $result[2]['str3']);
210
        self::assertEquals('Jonathan W.', $result[3]['str3']);
211
    }
212
213
    public function testOperatorAdd() : void
214
    {
215
        $result = $this->em->createQuery('SELECT m, m.salary+2500 AS add FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
216
                ->getResult();
217
218
        self::assertCount(4, $result);
219
        self::assertEquals(102500, $result[0]['add']);
220
        self::assertEquals(202500, $result[1]['add']);
221
        self::assertEquals(402500, $result[2]['add']);
222
        self::assertEquals(802500, $result[3]['add']);
223
    }
224
225
    public function testOperatorSub() : void
226
    {
227
        $result = $this->em->createQuery('SELECT m, m.salary-2500 AS sub FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
228
                ->getResult();
229
230
        self::assertCount(4, $result);
231
        self::assertEquals(97500, $result[0]['sub']);
232
        self::assertEquals(197500, $result[1]['sub']);
233
        self::assertEquals(397500, $result[2]['sub']);
234
        self::assertEquals(797500, $result[3]['sub']);
235
    }
236
237
    public function testOperatorMultiply() : void
238
    {
239
        $result = $this->em->createQuery('SELECT m, m.salary*2 AS op FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
240
                ->getResult();
241
242
        self::assertCount(4, $result);
243
        self::assertEquals(200000, $result[0]['op']);
244
        self::assertEquals(400000, $result[1]['op']);
245
        self::assertEquals(800000, $result[2]['op']);
246
        self::assertEquals(1600000, $result[3]['op']);
247
    }
248
249
    /**
250
     * @group test
251
     */
252
    public function testOperatorDiv() : void
253
    {
254
        $result = $this->em->createQuery('SELECT m, (m.salary/0.5) AS op FROM Doctrine\Tests\Models\Company\CompanyManager m ORDER BY m.salary ASC')
255
                ->getResult();
256
257
        self::assertCount(4, $result);
258
        self::assertEquals(200000, $result[0]['op']);
259
        self::assertEquals(400000, $result[1]['op']);
260
        self::assertEquals(800000, $result[2]['op']);
261
        self::assertEquals(1600000, $result[3]['op']);
262
    }
263
264
    public function testConcatFunction() : void
265
    {
266
        $arg = $this->em->createQuery('SELECT CONCAT(m.name, m.department) AS namedep FROM Doctrine\Tests\Models\Company\CompanyManager m order by namedep desc')
267
                ->getArrayResult();
268
269
        self::assertCount(4, $arg);
270
        self::assertEquals('Roman B.IT', $arg[0]['namedep']);
271
        self::assertEquals('Jonathan W.Administration', $arg[1]['namedep']);
272
        self::assertEquals('Guilherme B.Complaint Department', $arg[2]['namedep']);
273
        self::assertEquals('Benjamin E.HR', $arg[3]['namedep']);
274
    }
275
276
    /**
277
     * @group DDC-1014
278
     */
279
    public function testDateDiff() : void
280
    {
281
        $query = $this->em->createQuery("SELECT DATE_DIFF(CURRENT_TIMESTAMP(), DATE_ADD(CURRENT_TIMESTAMP(), 10, 'day')) AS diff FROM Doctrine\Tests\Models\Company\CompanyManager m");
282
        $arg   = $query->getArrayResult();
283
284
        self::assertEquals(-10, $arg[0]['diff'], 'Should be roughly -10 (or -9)', 1);
285
286
        $query = $this->em->createQuery("SELECT DATE_DIFF(DATE_ADD(CURRENT_TIMESTAMP(), 10, 'day'), CURRENT_TIMESTAMP()) AS diff FROM Doctrine\Tests\Models\Company\CompanyManager m");
287
        $arg   = $query->getArrayResult();
288
289
        self::assertEquals(10, $arg[0]['diff'], 'Should be roughly 10 (or 9)', 1);
290
    }
291
292
    /**
293
     * @group DDC-1014
294
     * @group DDC-2938
295
     * @dataProvider dateAddSubProvider
296
     */
297
    public function testDateAdd(string $unit, int $amount, int $delta = 0) : void
298
    {
299
        $query = sprintf(
300
            'SELECT CURRENT_TIMESTAMP() as now, DATE_ADD(CURRENT_TIMESTAMP(), %d, \'%s\') AS add FROM %s m',
301
            $amount,
302
            $unit,
303
            CompanyManager::class
304
        );
305
306
        $result = $this->em->createQuery($query)
307
                            ->setMaxResults(1)
308
                            ->getSingleResult(AbstractQuery::HYDRATE_ARRAY);
309
310
        self::assertArrayHasKey('now', $result);
311
        self::assertArrayHasKey('add', $result);
312
313
        self::assertEquals(
314
            (new DateTimeImmutable($result['now']))->modify(sprintf('+%d %s', $amount, $unit)),
315
            new DateTimeImmutable($result['add']),
316
            '',
317
            $delta
318
        );
319
    }
320
321
    /**
322
     * @group DDC-1014
323
     * @group DDC-2938
324
     * @dataProvider dateAddSubProvider
325
     */
326
    public function testDateSub(string $unit, int $amount, int $delta = 0) : void
327
    {
328
        $query = sprintf(
329
            'SELECT CURRENT_TIMESTAMP() as now, DATE_SUB(CURRENT_TIMESTAMP(), %d, \'%s\') AS sub FROM %s m',
330
            $amount,
331
            $unit,
332
            CompanyManager::class
333
        );
334
335
        $result = $this->em->createQuery($query)
336
                           ->setMaxResults(1)
337
                           ->getSingleResult(AbstractQuery::HYDRATE_ARRAY);
338
339
        self::assertArrayHasKey('now', $result);
340
        self::assertArrayHasKey('sub', $result);
341
342
        self::assertEquals(
343
            (new DateTimeImmutable($result['now']))->modify(sprintf('-%d %s', $amount, $unit)),
344
            new DateTimeImmutable($result['sub']),
345
            '',
346
            $delta
347
        );
348
    }
349
350
    public function dateAddSubProvider() : array
351
    {
352
        $secondsInDay = 86400;
353
354
        return [
355
            'year'   => ['year', 1, $secondsInDay],
356
            'month'  => ['month', 1, $secondsInDay],
357
            'week'   => ['week', 1, $secondsInDay],
358
            'day'    => ['day', 2, $secondsInDay],
359
            'hour'   => ['hour', 1, 3600],
360
            'minute' => ['minute', 1, 60],
361
            'second' => ['second', 10, 10],
362
        ];
363
    }
364
365
    /**
366
     * @group DDC-1213
367
     */
368
    public function testBitOrComparison() : void
369
    {
370
        $dql    = 'SELECT m, ' .
371
                    'BIT_OR(4, 2) AS bit_or,' .
372
                    'BIT_OR( (m.salary/100000) , 2 ) AS salary_bit_or ' .
373
                    'FROM Doctrine\Tests\Models\Company\CompanyManager m ' .
374
                'ORDER BY ' .
375
                    'm.id ';
376
        $result = $this->em->createQuery($dql)->getArrayResult();
377
378
        self::assertEquals(4 | 2, $result[0]['bit_or']);
379
        self::assertEquals(4 | 2, $result[1]['bit_or']);
380
        self::assertEquals(4 | 2, $result[2]['bit_or']);
381
        self::assertEquals(4 | 2, $result[3]['bit_or']);
382
383
        self::assertEquals(($result[0][0]['salary']/100000) | 2, $result[0]['salary_bit_or']);
384
        self::assertEquals(($result[1][0]['salary']/100000) | 2, $result[1]['salary_bit_or']);
385
        self::assertEquals(($result[2][0]['salary']/100000) | 2, $result[2]['salary_bit_or']);
386
        self::assertEquals(($result[3][0]['salary']/100000) | 2, $result[3]['salary_bit_or']);
387
    }
388
389
    /**
390
     * @group DDC-1213
391
     */
392
    public function testBitAndComparison() : void
393
    {
394
        $dql    = 'SELECT m, ' .
395
                    'BIT_AND(4, 2) AS bit_and,' .
396
                    'BIT_AND( (m.salary/100000) , 2 ) AS salary_bit_and ' .
397
                    'FROM Doctrine\Tests\Models\Company\CompanyManager m ' .
398
                'ORDER BY ' .
399
                    'm.id ';
400
        $result = $this->em->createQuery($dql)->getArrayResult();
401
402
        self::assertEquals(4 & 2, $result[0]['bit_and']);
403
        self::assertEquals(4 & 2, $result[1]['bit_and']);
404
        self::assertEquals(4 & 2, $result[2]['bit_and']);
405
        self::assertEquals(4 & 2, $result[3]['bit_and']);
406
407
        self::assertEquals(($result[0][0]['salary']/100000) & 2, $result[0]['salary_bit_and']);
408
        self::assertEquals(($result[1][0]['salary']/100000) & 2, $result[1]['salary_bit_and']);
409
        self::assertEquals(($result[2][0]['salary']/100000) & 2, $result[2]['salary_bit_and']);
410
        self::assertEquals(($result[3][0]['salary']/100000) & 2, $result[3]['salary_bit_and']);
411
    }
412
413
    protected function generateFixture()
414
    {
415
        $manager1 = new CompanyManager();
416
        $manager1->setName('Roman B.');
417
        $manager1->setTitle('Foo');
418
        $manager1->setDepartment('IT');
419
        $manager1->setSalary(100000);
420
421
        $manager2 = new CompanyManager();
422
        $manager2->setName('Benjamin E.');
423
        $manager2->setTitle('Foo');
424
        $manager2->setDepartment('HR');
425
        $manager2->setSalary(200000);
426
427
        $manager3 = new CompanyManager();
428
        $manager3->setName('Guilherme B.');
429
        $manager3->setTitle('Foo');
430
        $manager3->setDepartment('Complaint Department');
431
        $manager3->setSalary(400000);
432
433
        $manager4 = new CompanyManager();
434
        $manager4->setName('Jonathan W.');
435
        $manager4->setTitle('Foo');
436
        $manager4->setDepartment('Administration');
437
        $manager4->setSalary(800000);
438
439
        $this->em->persist($manager1);
440
        $this->em->persist($manager2);
441
        $this->em->persist($manager3);
442
        $this->em->persist($manager4);
443
        $this->em->flush();
444
        $this->em->clear();
445
    }
446
}
447