Failed Conditions
CANCELLED  
Pull Request — master (#7095)
by Benjamin
10:13
created

NativeQueryTest::getResultSetMapping()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\ORM\Functional;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\DBAL\Types\Type as DBALType;
9
use Doctrine\ORM\AbstractQuery;
10
use Doctrine\ORM\Internal\Hydration\HydrationException;
11
use Doctrine\ORM\PersistentCollection;
12
use Doctrine\ORM\Query\Parameter;
13
use Doctrine\ORM\Query\ResultSetMapping;
14
use Doctrine\ORM\Query\ResultSetMappingBuilder;
15
use Doctrine\Tests\Models\CMS\CmsAddress;
16
use Doctrine\Tests\Models\CMS\CmsEmail;
17
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
18
use Doctrine\Tests\Models\CMS\CmsUser;
19
use Doctrine\Tests\Models\Company\CompanyContract;
20
use Doctrine\Tests\Models\Company\CompanyEmployee;
21
use Doctrine\Tests\Models\Company\CompanyFixContract;
22
use Doctrine\Tests\Models\Company\CompanyFlexContract;
23
use Doctrine\Tests\Models\Company\CompanyPerson;
24
use Doctrine\Tests\Models\DDC3899\DDC3899FixContract;
25
use Doctrine\Tests\Models\DDC3899\DDC3899User;
26
use Doctrine\Tests\OrmFunctionalTestCase;
27
28
/**
29
 * NativeQueryTest
30
 *
31
 * @author robo
32
 */
33
class NativeQueryTest extends OrmFunctionalTestCase
34
{
35
    private $platform;
36
37
    protected function setUp()
38
    {
39
        $this->useModelSet('cms');
40
        $this->useModelSet('company');
41
42
        parent::setUp();
43
44
        $this->platform = $this->em->getConnection()->getDatabasePlatform();
45
    }
46
47
    public function testBasicNativeQuery()
48
    {
49
        $user = new CmsUser;
50
51
        $user->name = 'Roman';
52
        $user->username = 'romanb';
53
        $user->status = 'dev';
54
55
        $this->em->persist($user);
56
        $this->em->flush();
57
        $this->em->clear();
58
59
        $rsm = new ResultSetMapping;
60
61
        $rsm->addEntityResult(CmsUser::class, 'u');
62
        $rsm->addFieldResult('u', $this->platform->getSQLResultCasing('id'), 'id');
63
        $rsm->addFieldResult('u', $this->platform->getSQLResultCasing('name'), 'name');
64
65
        $query = $this->em->createNativeQuery('SELECT id, name FROM cms_users WHERE username = ?', $rsm);
66
67
        $query->setParameter(1, 'romanb');
68
69
        $users = $query->getResult();
70
71
        self::assertCount(1, $users);
72
        self::assertInstanceOf(CmsUser::class, $users[0]);
73
        self::assertEquals('Roman', $users[0]->name);
74
    }
75
76
    public function testBasicNativeQueryWithMetaResult()
77
    {
78
        $user = new CmsUser;
79
80
        $user->name = 'Roman';
81
        $user->username = 'romanb';
82
        $user->status = 'dev';
83
84
        $addr = new CmsAddress;
85
86
        $addr->country = 'germany';
87
        $addr->zip = 10827;
88
        $addr->city = 'Berlin';
89
90
        $user->setAddress($addr);
91
92
        $this->em->persist($user);
93
        $this->em->flush();
94
        $this->em->clear();
95
96
        $rsm = new ResultSetMapping;
97
98
        $rsm->addEntityResult(CmsAddress::class, 'a');
99
        $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('id'), 'id');
100
        $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('country'), 'country');
101
        $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('zip'), 'zip');
102
        $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('city'), 'city');
103
        $rsm->addMetaResult('a', $this->platform->getSQLResultCasing('user_id'), 'user_id', false, DBALType::getType('integer'));
104
105
        $query = $this->em->createNativeQuery('SELECT a.id, a.country, a.zip, a.city, a.user_id FROM cms_addresses a WHERE a.id = ?', $rsm);
106
107
        $query->setParameter(1, $addr->id);
108
109
        $addresses = $query->getResult();
110
111
        self::assertCount(1, $addresses);
112
        self::assertInstanceOf(CmsAddress::class, $addresses[0]);
113
        self::assertEquals($addr->country, $addresses[0]->country);
114
        self::assertEquals($addr->zip, $addresses[0]->zip);
115
        self::assertEquals($addr->city, $addresses[0]->city);
116
        self::assertEquals($addr->street, $addresses[0]->street);
117
        self::assertInstanceOf(CmsUser::class, $addresses[0]->user);
118
    }
119
120
    public function testJoinedOneToManyNativeQuery()
121
    {
122
        $user = new CmsUser;
123
124
        $user->name = 'Roman';
125
        $user->username = 'romanb';
126
        $user->status = 'dev';
127
128
        $phone = new CmsPhonenumber;
129
130
        $phone->phonenumber = 424242;
131
132
        $user->addPhonenumber($phone);
133
134
        $this->em->persist($user);
135
        $this->em->flush();
136
        $this->em->clear();
137
138
        $rsm = new ResultSetMapping;
139
140
        $rsm->addEntityResult(CmsUser::class, 'u');
141
        $rsm->addFieldResult('u', $this->platform->getSQLResultCasing('id'), 'id');
142
        $rsm->addFieldResult('u', $this->platform->getSQLResultCasing('name'), 'name');
143
        $rsm->addFieldResult('u', $this->platform->getSQLResultCasing('status'), 'status');
144
        $rsm->addJoinedEntityResult(CmsPhonenumber::class, 'p', 'u', 'phonenumbers');
145
        $rsm->addFieldResult('p', $this->platform->getSQLResultCasing('phonenumber'), 'phonenumber');
146
147
        $query = $this->em->createNativeQuery('SELECT id, name, status, phonenumber FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?', $rsm);
148
149
        $query->setParameter(1, 'romanb');
150
151
        $users = $query->getResult();
152
153
        self::assertCount(1, $users);
154
        self::assertInstanceOf(CmsUser::class, $users[0]);
155
        self::assertEquals('Roman', $users[0]->name);
156
        self::assertInstanceOf(PersistentCollection::class, $users[0]->getPhonenumbers());
157
        self::assertTrue($users[0]->getPhonenumbers()->isInitialized());
158
        self::assertCount(1, $users[0]->getPhonenumbers());
159
160
        $phones = $users[0]->getPhonenumbers();
161
162
        self::assertEquals(424242, $phones[0]->phonenumber);
163
        self::assertSame($phones[0]->getUser(), $users[0]);
164
    }
165
166
    public function testJoinedOneToOneNativeQuery()
167
    {
168
        $user = new CmsUser;
169
170
        $user->name = 'Roman';
171
        $user->username = 'romanb';
172
        $user->status = 'dev';
173
174
        $addr = new CmsAddress;
175
176
        $addr->country = 'germany';
177
        $addr->zip = 10827;
178
        $addr->city = 'Berlin';
179
180
        $user->setAddress($addr);
181
182
        $this->em->persist($user);
183
        $this->em->flush();
184
        $this->em->clear();
185
186
        $rsm = new ResultSetMapping;
187
188
        $rsm->addEntityResult(CmsUser::class, 'u');
189
        $rsm->addFieldResult('u', $this->platform->getSQLResultCasing('id'), 'id');
190
        $rsm->addFieldResult('u', $this->platform->getSQLResultCasing('name'), 'name');
191
        $rsm->addFieldResult('u', $this->platform->getSQLResultCasing('status'), 'status');
192
        $rsm->addJoinedEntityResult(CmsAddress::class, 'a', 'u', 'address');
193
        $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('a_id'), 'id');
194
        $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('country'), 'country');
195
        $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('zip'), 'zip');
196
        $rsm->addFieldResult('a', $this->platform->getSQLResultCasing('city'), 'city');
197
198
        $query = $this->em->createNativeQuery('SELECT u.id, u.name, u.status, a.id AS a_id, a.country, a.zip, a.city FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?', $rsm);
199
200
        $query->setParameter(1, 'romanb');
201
202
        $users = $query->getResult();
203
204
        self::assertCount(1, $users);
205
        self::assertInstanceOf(CmsUser::class, $users[0]);
206
        self::assertEquals('Roman', $users[0]->name);
207
        self::assertInstanceOf(PersistentCollection::class, $users[0]->getPhonenumbers());
208
        self::assertFalse($users[0]->getPhonenumbers()->isInitialized());
209
        self::assertInstanceOf(CmsAddress::class, $users[0]->getAddress());
210
        self::assertEquals($users[0]->getAddress()->getUser(), $users[0]);
211
        self::assertEquals('germany', $users[0]->getAddress()->getCountry());
212
        self::assertEquals(10827, $users[0]->getAddress()->getZipCode());
213
        self::assertEquals('Berlin', $users[0]->getAddress()->getCity());
214
    }
215
216
    public function testFluentInterface()
217
    {
218
        $parameters = new ArrayCollection;
219
220
        $parameters->add(new Parameter(1, 'foo'));
221
        $parameters->add(new Parameter(2, 'bar'));
222
223
        $rsm = new ResultSetMapping;
224
225
        $q = $this->em->createNativeQuery('SELECT id, name, status, phonenumber FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?', $rsm);
226
        $q2 = $q->setSQL('foo')
227
          ->setResultSetMapping($rsm)
228
          ->expireResultCache(true)
229
          ->setHint('foo', 'bar')
230
          ->setParameter(1, 'foo')
231
          ->setParameters($parameters)
232
          ->setResultCacheDriver(null)
233
          ->setResultCacheLifetime(3500);
234
235
        self::assertSame($q, $q2);
236
    }
237
238
    public function testJoinedOneToManyNativeQueryWithRSMBuilder()
239
    {
240
        $user = new CmsUser;
241
242
        $user->name = 'Roman';
243
        $user->username = 'romanb';
244
        $user->status = 'dev';
245
246
        $phone = new CmsPhonenumber;
247
248
        $phone->phonenumber = 424242;
249
250
        $user->addPhonenumber($phone);
251
252
        $this->em->persist($user);
253
        $this->em->flush();
254
        $this->em->clear();
255
256
        $rsm = new ResultSetMappingBuilder($this->em);
257
258
        $rsm->addRootEntityFromClassMetadata(CmsUser::class, 'u');
259
        $rsm->addJoinedEntityFromClassMetadata(CmsPhonenumber::class, 'p', 'u', 'phonenumbers');
260
        $query = $this->em->createNativeQuery('SELECT u.*, p.* FROM cms_users u LEFT JOIN cms_phonenumbers p ON u.id = p.user_id WHERE username = ?', $rsm);
261
262
        $query->setParameter(1, 'romanb');
263
264
        $users = $query->getResult();
265
266
        self::assertCount(1, $users);
267
        self::assertInstanceOf(CmsUser::class, $users[0]);
268
        self::assertEquals('Roman', $users[0]->name);
269
        self::assertInstanceOf(PersistentCollection::class, $users[0]->getPhonenumbers());
270
        self::assertTrue($users[0]->getPhonenumbers()->isInitialized());
271
        self::assertCount(1, $users[0]->getPhonenumbers());
272
273
        $phones = $users[0]->getPhonenumbers();
274
275
        self::assertEquals(424242, $phones[0]->phonenumber);
276
        self::assertSame($phones[0]->getUser(), $users[0]);
277
278
        $this->em->clear();
279
280
        $rsm = new ResultSetMappingBuilder($this->em);
281
282
        $rsm->addRootEntityFromClassMetadata(CmsPhonenumber::class, 'p');
283
284
        $query = $this->em->createNativeQuery('SELECT p.* FROM cms_phonenumbers p WHERE p.phonenumber = ?', $rsm);
285
286
        $query->setParameter(1, $phone->phonenumber);
287
288
        $phone = $query->getSingleResult();
289
290
        self::assertNotNull($phone->getUser());
291
        self::assertEquals($user->name, $phone->getUser()->getName());
292
    }
293
294
    public function testJoinedOneToOneNativeQueryWithRSMBuilder()
295
    {
296
        $user = new CmsUser;
297
298
        $user->name = 'Roman';
299
        $user->username = 'romanb';
300
        $user->status = 'dev';
301
302
        $addr = new CmsAddress;
303
304
        $addr->country = 'germany';
305
        $addr->zip = 10827;
306
        $addr->city = 'Berlin';
307
308
        $user->setAddress($addr);
309
310
        $this->em->persist($user);
311
        $this->em->flush();
312
        $this->em->clear();
313
314
        $rsm = new ResultSetMappingBuilder($this->em);
315
316
        $rsm->addRootEntityFromClassMetadata(CmsUser::class, 'u');
317
        $rsm->addJoinedEntityFromClassMetadata(CmsAddress::class, 'a', 'u', 'address', ['id' => 'a_id']);
318
319
        $query = $this->em->createNativeQuery('SELECT u.*, a.*, a.id AS a_id FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?', $rsm);
320
321
        $query->setParameter(1, 'romanb');
322
323
        $users = $query->getResult();
324
325
        self::assertCount(1, $users);
326
        self::assertInstanceOf(CmsUser::class, $users[0]);
327
        self::assertEquals('Roman', $users[0]->name);
328
        self::assertInstanceOf(PersistentCollection::class, $users[0]->getPhonenumbers());
329
        self::assertFalse($users[0]->getPhonenumbers()->isInitialized());
330
        self::assertInstanceOf(CmsAddress::class, $users[0]->getAddress());
331
        self::assertEquals($users[0]->getAddress()->getUser(), $users[0]);
332
        self::assertEquals('germany', $users[0]->getAddress()->getCountry());
333
        self::assertEquals(10827, $users[0]->getAddress()->getZipCode());
334
        self::assertEquals('Berlin', $users[0]->getAddress()->getCity());
335
336
        $this->em->clear();
337
338
        $rsm = new ResultSetMappingBuilder($this->em);
339
340
        $rsm->addRootEntityFromClassMetadata(CmsAddress::class, 'a');
341
342
        $query = $this->em->createNativeQuery('SELECT a.* FROM cms_addresses a WHERE a.id = ?', $rsm);
343
344
        $query->setParameter(1, $addr->getId());
345
346
        $address = $query->getSingleResult();
347
348
        self::assertNotNull($address->getUser());
349
        self::assertEquals($user->name, $address->getUser()->getName());
350
    }
351
352
    /**
353
     * @group rsm-sti
354
     */
355
    public function testConcreteClassInSingleTableInheritanceSchemaWithRSMBuilderIsFine()
356
    {
357
        $rsm = new ResultSetMappingBuilder($this->em);
358
359
        $rsm->addRootEntityFromClassMetadata(CompanyFixContract::class, 'c');
360
361
        self::assertSame(CompanyFixContract::class, $rsm->getClassName('c'));
362
    }
363
364
    /**
365
     * @group rsm-sti
366
     */
367
    public function testAbstractClassInSingleTableInheritanceSchemaWithRSMBuilderThrowsException()
368
    {
369
        $this->expectException(\InvalidArgumentException::class);
370
        $this->expectExceptionMessage('ResultSetMapping builder does not currently support your inheritance scheme.');
371
372
        $rsm = new ResultSetMappingBuilder($this->em);
373
374
        $rsm->addRootEntityFromClassMetadata(CompanyContract::class, 'c');
375
    }
376
377
    /**
378
     * @expectedException \InvalidArgumentException
379
     */
380
    public function testRSMBuilderThrowsExceptionOnColumnConflict()
381
    {
382
        $rsm = new ResultSetMappingBuilder($this->em);
383
384
        $rsm->addRootEntityFromClassMetadata(CmsUser::class, 'u');
385
        $rsm->addJoinedEntityFromClassMetadata(CmsAddress::class, 'a', 'u', 'address');
386
    }
387
388
    /**
389
     * @group PR-39
390
     */
391
    public function testUnknownParentAliasThrowsException()
392
    {
393
        $rsm = new ResultSetMappingBuilder($this->em);
394
395
        $rsm->addRootEntityFromClassMetadata(CmsUser::class, 'u');
396
        $rsm->addJoinedEntityFromClassMetadata(CmsAddress::class, 'a', 'un', 'address', ['id' => 'a_id']);
397
398
        $query = $this->em->createNativeQuery('SELECT u.*, a.*, a.id AS a_id FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?', $rsm);
399
400
        $query->setParameter(1, 'romanb');
401
402
        $this->expectException(HydrationException::class);
403
        $this->expectExceptionMessage("The parent object of entity result with alias 'a' was not found. The parent alias is 'un'.");
404
405
        $query->getResult();
406
    }
407
408
    /**
409
     * @group DDC-2055
410
     */
411
    public function testGenerateSelectClauseNoRenameSingleEntity()
412
    {
413
        $rsm = new ResultSetMappingBuilder($this->em);
414
415
        $rsm->addRootEntityFromClassMetadata(CmsUser::class, 'u');
416
417
        $selectClause = $rsm->generateSelectClause();
418
419
        self::assertSQLEquals('u.id AS id, u.status AS status, u.username AS username, u.name AS name, u.email_id AS email_id', $selectClause);
420
    }
421
422
    /**
423
     * @group DDC-2055
424
     */
425
    public function testGenerateSelectClauseCustomRenames()
426
    {
427
        $rsm = new ResultSetMappingBuilder($this->em);
428
429
        $rsm->addRootEntityFromClassMetadata(
430
            CmsUser::class,
431
            'u',
432
            [
433
                'id' => 'id1',
434
                'username' => 'username2'
435
            ]
436
        );
437
438
        $selectClause = $rsm->generateSelectClause();
439
440
        self::assertSQLEquals('u.id AS id1, u.status AS status, u.username AS username2, u.name AS name, u.email_id AS email_id', $selectClause);
441
    }
442
443
    /**
444
     * @group DDC-2055
445
     */
446
    public function testGenerateSelectClauseRenameTableAlias()
447
    {
448
        $rsm = new ResultSetMappingBuilder($this->em);
449
450
        $rsm->addRootEntityFromClassMetadata(CmsUser::class, 'u');
451
452
        $selectClause = $rsm->generateSelectClause(['u' => 'u1']);
453
454
        self::assertSQLEquals('u1.id AS id, u1.status AS status, u1.username AS username, u1.name AS name, u1.email_id AS email_id', $selectClause);
455
    }
456
457
    /**
458
     * @group DDC-2055
459
     */
460
    public function testGenerateSelectClauseIncrement()
461
    {
462
        $rsm = new ResultSetMappingBuilder($this->em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT);
463
464
        $rsm->addRootEntityFromClassMetadata(CmsUser::class, 'u');
465
466
        $selectClause = $rsm->generateSelectClause();
467
468
        self::assertSQLEquals('u.id AS id0, u.status AS status1, u.username AS username2, u.name AS name3, u.email_id AS email_id4', $selectClause);
469
    }
470
471
    /**
472
     * @group DDC-2055
473
     */
474
    public function testGenerateSelectClauseToString()
475
    {
476
        $rsm = new ResultSetMappingBuilder($this->em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT);
477
478
        $rsm->addRootEntityFromClassMetadata(CmsUser::class, 'u');
479
480
        self::assertSQLEquals('u.id AS id0, u.status AS status1, u.username AS username2, u.name AS name3, u.email_id AS email_id4', (string)$rsm);
481
    }
482
483
    /**
484
     * @group DDC-3899
485
     */
486
    public function testGenerateSelectClauseWithDiscriminatorColumn()
487
    {
488
        $rsm = new ResultSetMappingBuilder($this->em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT);
489
490
        $rsm->addEntityResult(DDC3899User::class, 'u');
491
        $rsm->addJoinedEntityResult(DDC3899FixContract::class, 'c', 'u', 'contracts');
492
        $rsm->addFieldResult('u', $this->platform->getSQLResultCasing('id'), 'id');
493
        $rsm->setDiscriminatorColumn('c', $this->platform->getSQLResultCasing('discr'));
494
495
        $selectClause = $rsm->generateSelectClause(['u' => 'u1', 'c' => 'c1']);
496
497
        self::assertSQLEquals('u1.id as id, c1.discr as discr', $selectClause);
498
    }
499
500
    protected function getResultSetMapping(AbstractQuery $query) : ResultSetMapping
501
    {
502
        $reflClass  = new \ReflectionClass($query);
503
        $reflMethod = $reflClass->getMethod('getResultSetMapping');
504
505
        $reflMethod->setAccessible(true);
506
507
        return $reflMethod->invoke($query);
508
    }
509
}
510