1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Doctrine\Tests\ORM\Cache; |
4
|
|
|
|
5
|
|
|
use Doctrine\Common\Collections\Collection; |
6
|
|
|
use Doctrine\ORM\Cache\EntityCacheKey; |
7
|
|
|
use Doctrine\ORM\Cache\QueryCache; |
8
|
|
|
use Doctrine\Tests\Mocks\TimestampRegionMock; |
9
|
|
|
use Doctrine\Tests\OrmTestCase; |
10
|
|
|
use Doctrine\Tests\Mocks\CacheRegionMock; |
11
|
|
|
use Doctrine\ORM\Cache\DefaultQueryCache; |
12
|
|
|
use Doctrine\ORM\Cache\QueryCacheKey; |
13
|
|
|
use Doctrine\ORM\Cache\QueryCacheEntry; |
14
|
|
|
use Doctrine\ORM\Query\ResultSetMappingBuilder; |
15
|
|
|
use Doctrine\Tests\Models\Cache\Country; |
16
|
|
|
use Doctrine\Tests\Models\Cache\City; |
17
|
|
|
use Doctrine\Tests\Models\Cache\State; |
18
|
|
|
use Doctrine\Tests\Models\Cache\Restaurant; |
19
|
|
|
use Doctrine\ORM\EntityManagerInterface; |
20
|
|
|
use Doctrine\Tests\Models\Generic\BooleanModel; |
21
|
|
|
use Doctrine\ORM\Cache\EntityCacheEntry; |
22
|
|
|
use Doctrine\ORM\Cache; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @group DDC-2183 |
26
|
|
|
*/ |
27
|
|
|
class DefaultQueryCacheTest extends OrmTestCase |
28
|
|
|
{ |
29
|
|
|
/** |
30
|
|
|
* @var \Doctrine\ORM\Cache\DefaultQueryCache |
31
|
|
|
*/ |
32
|
|
|
private $queryCache; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var \Doctrine\ORM\EntityManager |
36
|
|
|
*/ |
37
|
|
|
private $em; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var \Doctrine\Tests\Mocks\CacheRegionMock |
41
|
|
|
*/ |
42
|
|
|
private $region; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @var \Doctrine\Tests\ORM\Cache\CacheFactoryDefaultQueryCacheTest |
46
|
|
|
*/ |
47
|
|
|
private $cacheFactory; |
48
|
|
|
|
49
|
|
|
protected function setUp() |
50
|
|
|
{ |
51
|
|
|
parent::setUp(); |
52
|
|
|
|
53
|
|
|
$this->enableSecondLevelCache(); |
54
|
|
|
|
55
|
|
|
$this->em = $this->_getTestEntityManager(); |
56
|
|
|
$this->region = new CacheRegionMock(); |
57
|
|
|
$this->queryCache = new DefaultQueryCache($this->em, $this->region); |
58
|
|
|
$this->cacheFactory = new CacheFactoryDefaultQueryCacheTest($this->queryCache, $this->region); |
59
|
|
|
|
60
|
|
|
$this->em->getConfiguration() |
61
|
|
|
->getSecondLevelCacheConfiguration() |
62
|
|
|
->setCacheFactory($this->cacheFactory); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
public function testImplementQueryCache() |
66
|
|
|
{ |
67
|
|
|
$this->assertInstanceOf(QueryCache::class, $this->queryCache); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
public function testGetRegion() |
71
|
|
|
{ |
72
|
|
|
$this->assertSame($this->region, $this->queryCache->getRegion()); |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
public function testClearShouldEvictRegion() |
76
|
|
|
{ |
77
|
|
|
$this->queryCache->clear(); |
78
|
|
|
|
79
|
|
|
$this->assertArrayHasKey('evictAll', $this->region->calls); |
80
|
|
|
$this->assertCount(1, $this->region->calls['evictAll']); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
public function testPutBasicQueryResult() |
84
|
|
|
{ |
85
|
|
|
$result = []; |
86
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
87
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
88
|
|
|
$metadata = $this->em->getClassMetadata(Country::class); |
89
|
|
|
|
90
|
|
|
$rsm->addRootEntityFromClassMetadata(Country::class, 'c'); |
91
|
|
|
|
92
|
|
View Code Duplication |
for ($i = 0; $i < 4; $i++) { |
|
|
|
|
93
|
|
|
$name = "Country $i"; |
94
|
|
|
$entity = new Country($name); |
95
|
|
|
$result[] = $entity; |
96
|
|
|
|
97
|
|
|
$metadata->setFieldValue($entity, 'id', $i); |
98
|
|
|
$this->em->getUnitOfWork()->registerManaged($entity, ['id' => $i], ['name' => $name]); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
$this->assertTrue($this->queryCache->put($key, $rsm, $result)); |
102
|
|
|
$this->assertArrayHasKey('put', $this->region->calls); |
103
|
|
|
$this->assertCount(5, $this->region->calls['put']); |
104
|
|
|
|
105
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][0]['key']); |
106
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][1]['key']); |
107
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][2]['key']); |
108
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][3]['key']); |
109
|
|
|
$this->assertInstanceOf(QueryCacheKey::class, $this->region->calls['put'][4]['key']); |
110
|
|
|
|
111
|
|
|
$this->assertInstanceOf(EntityCacheEntry::class, $this->region->calls['put'][0]['entry']); |
112
|
|
|
$this->assertInstanceOf(EntityCacheEntry::class, $this->region->calls['put'][1]['entry']); |
113
|
|
|
$this->assertInstanceOf(EntityCacheEntry::class, $this->region->calls['put'][2]['entry']); |
114
|
|
|
$this->assertInstanceOf(EntityCacheEntry::class, $this->region->calls['put'][3]['entry']); |
115
|
|
|
$this->assertInstanceOf(QueryCacheEntry::class, $this->region->calls['put'][4]['entry']); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
public function testPutToOneAssociationQueryResult() |
119
|
|
|
{ |
120
|
|
|
$result = []; |
121
|
|
|
$uow = $this->em->getUnitOfWork(); |
122
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
123
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
124
|
|
|
$cityClass = $this->em->getClassMetadata(City::class); |
125
|
|
|
$stateClass = $this->em->getClassMetadata(State::class); |
126
|
|
|
|
127
|
|
|
$rsm->addRootEntityFromClassMetadata(City::class, 'c'); |
128
|
|
|
$rsm->addJoinedEntityFromClassMetadata(State::class, 's', 'c', 'state', ['id'=>'state_id', 'name'=>'state_name']); |
129
|
|
|
|
130
|
|
|
for ($i = 0; $i < 4; $i++) { |
131
|
|
|
$state = new State("State $i"); |
132
|
|
|
$city = new City("City $i", $state); |
133
|
|
|
$result[] = $city; |
134
|
|
|
|
135
|
|
|
$cityClass->setFieldValue($city, 'id', $i); |
136
|
|
|
$stateClass->setFieldValue($state, 'id', $i*2); |
137
|
|
|
|
138
|
|
|
$uow->registerManaged($state, ['id' => $state->getId()], ['name' => $city->getName()]); |
139
|
|
|
$uow->registerManaged($city, ['id' => $city->getId()], ['name' => $city->getName(), 'state' => $state]); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
$this->assertTrue($this->queryCache->put($key, $rsm, $result)); |
143
|
|
|
$this->assertArrayHasKey('put', $this->region->calls); |
144
|
|
|
$this->assertCount(9, $this->region->calls['put']); |
145
|
|
|
|
146
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][0]['key']); |
147
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][1]['key']); |
148
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][2]['key']); |
149
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][3]['key']); |
150
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][4]['key']); |
151
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][5]['key']); |
152
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][6]['key']); |
153
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][7]['key']); |
154
|
|
|
$this->assertInstanceOf(QueryCacheKey::class, $this->region->calls['put'][8]['key']); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
public function testPutToOneAssociation2LevelsQueryResult() |
158
|
|
|
{ |
159
|
|
|
$result = []; |
160
|
|
|
$uow = $this->em->getUnitOfWork(); |
161
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
162
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
163
|
|
|
$cityClass = $this->em->getClassMetadata(City::class); |
164
|
|
|
$stateClass = $this->em->getClassMetadata(State::class); |
165
|
|
|
$countryClass = $this->em->getClassMetadata(Country::class); |
166
|
|
|
|
167
|
|
|
$rsm->addRootEntityFromClassMetadata(City::class, 'c'); |
168
|
|
|
$rsm->addJoinedEntityFromClassMetadata(State::class, 's', 'c', 'state', ['id'=>'state_id', 'name'=>'state_name'] |
169
|
|
|
); |
170
|
|
|
$rsm->addJoinedEntityFromClassMetadata(Country::class, 'co', 's', 'country', ['id'=>'country_id', 'name'=>'country_name'] |
171
|
|
|
); |
172
|
|
|
|
173
|
|
|
for ($i = 0; $i < 4; $i++) { |
174
|
|
|
$country = new Country("Country $i"); |
175
|
|
|
$state = new State("State $i", $country); |
176
|
|
|
$city = new City("City $i", $state); |
177
|
|
|
|
178
|
|
|
$result[] = $city; |
179
|
|
|
|
180
|
|
|
$cityClass->setFieldValue($city, 'id', $i); |
181
|
|
|
$stateClass->setFieldValue($state, 'id', $i*2); |
182
|
|
|
$countryClass->setFieldValue($country, 'id', $i*3); |
183
|
|
|
|
184
|
|
|
$uow->registerManaged($country, ['id' => $country->getId()], ['name' => $country->getName()]); |
185
|
|
|
$uow->registerManaged($state, ['id' => $state->getId()], ['name' => $state->getName(), 'country' => $country] |
186
|
|
|
); |
187
|
|
|
$uow->registerManaged($city, ['id' => $city->getId()], ['name' => $city->getName(), 'state' => $state]); |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
$this->assertTrue($this->queryCache->put($key, $rsm, $result)); |
191
|
|
|
$this->assertArrayHasKey('put', $this->region->calls); |
192
|
|
|
$this->assertCount(13, $this->region->calls['put']); |
193
|
|
|
|
194
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][0]['key']); |
195
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][1]['key']); |
196
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][2]['key']); |
197
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][3]['key']); |
198
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][4]['key']); |
199
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][5]['key']); |
200
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][6]['key']); |
201
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][7]['key']); |
202
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][8]['key']); |
203
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][9]['key']); |
204
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][10]['key']); |
205
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][11]['key']); |
206
|
|
|
$this->assertInstanceOf(QueryCacheKey::class, $this->region->calls['put'][12]['key']); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
public function testPutToOneAssociationNullQueryResult() |
210
|
|
|
{ |
211
|
|
|
$result = []; |
212
|
|
|
$uow = $this->em->getUnitOfWork(); |
213
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
214
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
215
|
|
|
$cityClass = $this->em->getClassMetadata(City::class); |
216
|
|
|
|
217
|
|
|
$rsm->addRootEntityFromClassMetadata(City::class, 'c'); |
218
|
|
|
$rsm->addJoinedEntityFromClassMetadata(State::class, 's', 'c', 'state', ['id'=>'state_id', 'name'=>'state_name'] |
219
|
|
|
); |
220
|
|
|
|
221
|
|
|
for ($i = 0; $i < 4; $i++) { |
222
|
|
|
$city = new City("City $i", null); |
223
|
|
|
$result[] = $city; |
224
|
|
|
|
225
|
|
|
$cityClass->setFieldValue($city, 'id', $i); |
226
|
|
|
|
227
|
|
|
$uow->registerManaged($city, ['id' => $city->getId()], ['name' => $city->getName(), 'state' => null]); |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
$this->assertTrue($this->queryCache->put($key, $rsm, $result)); |
231
|
|
|
$this->assertArrayHasKey('put', $this->region->calls); |
232
|
|
|
$this->assertCount(5, $this->region->calls['put']); |
233
|
|
|
|
234
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][0]['key']); |
235
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][1]['key']); |
236
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][2]['key']); |
237
|
|
|
$this->assertInstanceOf(EntityCacheKey::class, $this->region->calls['put'][3]['key']); |
238
|
|
|
$this->assertInstanceOf(QueryCacheKey::class, $this->region->calls['put'][4]['key']); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
public function testPutToManyAssociationQueryResult() |
242
|
|
|
{ |
243
|
|
|
$result = []; |
244
|
|
|
$uow = $this->em->getUnitOfWork(); |
245
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
246
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
247
|
|
|
$cityClass = $this->em->getClassMetadata(City::class); |
248
|
|
|
$stateClass = $this->em->getClassMetadata(State::class); |
249
|
|
|
|
250
|
|
|
$rsm->addRootEntityFromClassMetadata(State::class, 's'); |
251
|
|
|
$rsm->addJoinedEntityFromClassMetadata(City::class, 'c', 's', 'cities', ['id'=>'c_id', 'name'=>'c_name']); |
252
|
|
|
|
253
|
|
|
for ($i = 0; $i < 4; $i++) { |
254
|
|
|
$state = new State("State $i"); |
255
|
|
|
$city1 = new City("City 1", $state); |
256
|
|
|
$city2 = new City("City 2", $state); |
257
|
|
|
$result[] = $state; |
258
|
|
|
|
259
|
|
|
$cityClass->setFieldValue($city1, 'id', $i + 11); |
260
|
|
|
$cityClass->setFieldValue($city2, 'id', $i + 22); |
261
|
|
|
$stateClass->setFieldValue($state, 'id', $i); |
262
|
|
|
|
263
|
|
|
$state->addCity($city1); |
264
|
|
|
$state->addCity($city2); |
265
|
|
|
|
266
|
|
|
$uow->registerManaged($city1, ['id' => $city1->getId()], ['name' => $city1->getName(), 'state' => $state] |
267
|
|
|
); |
268
|
|
|
$uow->registerManaged($city2, ['id' => $city2->getId()], ['name' => $city2->getName(), 'state' => $state] |
269
|
|
|
); |
270
|
|
|
$uow->registerManaged($state, ['id' => $state->getId()], ['name' => $state->getName(), 'cities' => $state->getCities()] |
271
|
|
|
); |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
$this->assertTrue($this->queryCache->put($key, $rsm, $result)); |
275
|
|
|
$this->assertArrayHasKey('put', $this->region->calls); |
276
|
|
|
$this->assertCount(13, $this->region->calls['put']); |
277
|
|
|
} |
278
|
|
|
|
279
|
|
View Code Duplication |
public function testGetBasicQueryResult() |
280
|
|
|
{ |
281
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
282
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
283
|
|
|
$entry = new QueryCacheEntry( |
284
|
|
|
[ |
285
|
|
|
['identifier' => ['id' => 1]], |
286
|
|
|
['identifier' => ['id' => 2]] |
287
|
|
|
] |
288
|
|
|
); |
289
|
|
|
|
290
|
|
|
$data = [ |
291
|
|
|
['id'=>1, 'name' => 'Foo'], |
292
|
|
|
['id'=>2, 'name' => 'Bar'] |
293
|
|
|
]; |
294
|
|
|
|
295
|
|
|
$this->region->addReturn('get', $entry); |
296
|
|
|
|
297
|
|
|
$this->region->addReturn( |
298
|
|
|
'getMultiple', |
299
|
|
|
[ |
300
|
|
|
new EntityCacheEntry(Country::class, $data[0]), |
301
|
|
|
new EntityCacheEntry(Country::class, $data[1]) |
302
|
|
|
] |
303
|
|
|
); |
304
|
|
|
|
305
|
|
|
$rsm->addRootEntityFromClassMetadata(Country::class, 'c'); |
306
|
|
|
|
307
|
|
|
$result = $this->queryCache->get($key, $rsm); |
308
|
|
|
|
309
|
|
|
$this->assertCount(2, $result); |
310
|
|
|
$this->assertInstanceOf(Country::class, $result[0]); |
311
|
|
|
$this->assertInstanceOf(Country::class, $result[1]); |
312
|
|
|
$this->assertEquals(1, $result[0]->getId()); |
313
|
|
|
$this->assertEquals(2, $result[1]->getId()); |
314
|
|
|
$this->assertEquals('Foo', $result[0]->getName()); |
315
|
|
|
$this->assertEquals('Bar', $result[1]->getName()); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
View Code Duplication |
public function testGetWithAssociation() |
319
|
|
|
{ |
320
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
321
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
322
|
|
|
$entry = new QueryCacheEntry( |
323
|
|
|
[ |
324
|
|
|
['identifier' => ['id' => 1]], |
325
|
|
|
['identifier' => ['id' => 2]] |
326
|
|
|
] |
327
|
|
|
); |
328
|
|
|
|
329
|
|
|
$data = [ |
330
|
|
|
['id'=>1, 'name' => 'Foo'], |
331
|
|
|
['id'=>2, 'name' => 'Bar'] |
332
|
|
|
]; |
333
|
|
|
|
334
|
|
|
$this->region->addReturn('get', $entry); |
335
|
|
|
|
336
|
|
|
$this->region->addReturn( |
337
|
|
|
'getMultiple', |
338
|
|
|
[ |
339
|
|
|
new EntityCacheEntry(Country::class, $data[0]), |
340
|
|
|
new EntityCacheEntry(Country::class, $data[1]) |
341
|
|
|
] |
342
|
|
|
); |
343
|
|
|
|
344
|
|
|
$rsm->addRootEntityFromClassMetadata(Country::class, 'c'); |
345
|
|
|
|
346
|
|
|
$result = $this->queryCache->get($key, $rsm); |
347
|
|
|
|
348
|
|
|
$this->assertCount(2, $result); |
349
|
|
|
$this->assertInstanceOf(Country::class, $result[0]); |
350
|
|
|
$this->assertInstanceOf(Country::class, $result[1]); |
351
|
|
|
$this->assertEquals(1, $result[0]->getId()); |
352
|
|
|
$this->assertEquals(2, $result[1]->getId()); |
353
|
|
|
$this->assertEquals('Foo', $result[0]->getName()); |
354
|
|
|
$this->assertEquals('Bar', $result[1]->getName()); |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
public function testCancelPutResultIfEntityPutFails() |
358
|
|
|
{ |
359
|
|
|
$result = []; |
360
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
361
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
362
|
|
|
$metadata = $this->em->getClassMetadata(Country::class); |
363
|
|
|
|
364
|
|
|
$rsm->addRootEntityFromClassMetadata(Country::class, 'c'); |
365
|
|
|
|
366
|
|
View Code Duplication |
for ($i = 0; $i < 4; $i++) { |
|
|
|
|
367
|
|
|
$name = "Country $i"; |
368
|
|
|
$entity = new Country($name); |
369
|
|
|
$result[] = $entity; |
370
|
|
|
|
371
|
|
|
$metadata->setFieldValue($entity, 'id', $i); |
372
|
|
|
$this->em->getUnitOfWork()->registerManaged($entity, ['id' => $i], ['name' => $name]); |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
$this->region->addReturn('put', false); |
376
|
|
|
|
377
|
|
|
$this->assertFalse($this->queryCache->put($key, $rsm, $result)); |
378
|
|
|
$this->assertArrayHasKey('put', $this->region->calls); |
379
|
|
|
$this->assertCount(1, $this->region->calls['put']); |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
public function testCancelPutResultIfAssociationEntityPutFails() |
383
|
|
|
{ |
384
|
|
|
$result = []; |
385
|
|
|
$uow = $this->em->getUnitOfWork(); |
386
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
387
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
388
|
|
|
$cityClass = $this->em->getClassMetadata(City::class); |
389
|
|
|
$stateClass = $this->em->getClassMetadata(State::class); |
390
|
|
|
|
391
|
|
|
$rsm->addRootEntityFromClassMetadata(City::class, 'c'); |
392
|
|
|
$rsm->addJoinedEntityFromClassMetadata(State::class, 's', 'c', 'state', ['id'=>'state_id', 'name'=>'state_name'] |
393
|
|
|
); |
394
|
|
|
|
395
|
|
|
$state = new State("State 1"); |
396
|
|
|
$city = new City("City 2", $state); |
397
|
|
|
$result[] = $city; |
398
|
|
|
|
399
|
|
|
$cityClass->setFieldValue($city, 'id', 1); |
400
|
|
|
$stateClass->setFieldValue($state, 'id', 11); |
401
|
|
|
|
402
|
|
|
$uow->registerManaged($state, ['id' => $state->getId()], ['name' => $city->getName()]); |
403
|
|
|
$uow->registerManaged($city, ['id' => $city->getId()], ['name' => $city->getName(), 'state' => $state]); |
404
|
|
|
|
405
|
|
|
$this->region->addReturn('put', true); // put root entity |
406
|
|
|
$this->region->addReturn('put', false); // association fails |
407
|
|
|
|
408
|
|
|
$this->assertFalse($this->queryCache->put($key, $rsm, $result)); |
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
public function testCancelPutToManyAssociationQueryResult() |
412
|
|
|
{ |
413
|
|
|
$result = []; |
414
|
|
|
$uow = $this->em->getUnitOfWork(); |
415
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
416
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
417
|
|
|
$cityClass = $this->em->getClassMetadata(City::class); |
418
|
|
|
$stateClass = $this->em->getClassMetadata(State::class); |
419
|
|
|
|
420
|
|
|
$rsm->addRootEntityFromClassMetadata(State::class, 's'); |
421
|
|
|
$rsm->addJoinedEntityFromClassMetadata(City::class, 'c', 's', 'cities', ['id'=>'c_id', 'name'=>'c_name']); |
422
|
|
|
|
423
|
|
|
$state = new State("State"); |
424
|
|
|
$city1 = new City("City 1", $state); |
425
|
|
|
$city2 = new City("City 2", $state); |
426
|
|
|
$result[] = $state; |
427
|
|
|
|
428
|
|
|
$stateClass->setFieldValue($state, 'id', 1); |
429
|
|
|
$cityClass->setFieldValue($city1, 'id', 11); |
430
|
|
|
$cityClass->setFieldValue($city2, 'id', 22); |
431
|
|
|
|
432
|
|
|
$state->addCity($city1); |
433
|
|
|
$state->addCity($city2); |
434
|
|
|
|
435
|
|
|
$uow->registerManaged($city1, ['id' => $city1->getId()], ['name' => $city1->getName(), 'state' => $state]); |
436
|
|
|
$uow->registerManaged($city2, ['id' => $city2->getId()], ['name' => $city2->getName(), 'state' => $state]); |
437
|
|
|
$uow->registerManaged($state, ['id' => $state->getId()], ['name' => $state->getName(), 'cities' => $state->getCities()] |
438
|
|
|
); |
439
|
|
|
|
440
|
|
|
$this->region->addReturn('put', true); // put root entity |
441
|
|
|
$this->region->addReturn('put', false); // collection association fails |
442
|
|
|
|
443
|
|
|
$this->assertFalse($this->queryCache->put($key, $rsm, $result)); |
444
|
|
|
$this->assertArrayHasKey('put', $this->region->calls); |
445
|
|
|
$this->assertCount(2, $this->region->calls['put']); |
446
|
|
|
} |
447
|
|
|
|
448
|
|
View Code Duplication |
public function testIgnoreCacheNonGetMode() |
449
|
|
|
{ |
450
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
451
|
|
|
$key = new QueryCacheKey('query.key1', 0, Cache::MODE_PUT); |
452
|
|
|
$entry = new QueryCacheEntry( |
453
|
|
|
[ |
454
|
|
|
['identifier' => ['id' => 1]], |
455
|
|
|
['identifier' => ['id' => 2]] |
456
|
|
|
] |
457
|
|
|
); |
458
|
|
|
|
459
|
|
|
$rsm->addRootEntityFromClassMetadata(Country::class, 'c'); |
460
|
|
|
|
461
|
|
|
$this->region->addReturn('get', $entry); |
462
|
|
|
|
463
|
|
|
$this->assertNull($this->queryCache->get($key, $rsm)); |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
public function testIgnoreCacheNonPutMode() |
467
|
|
|
{ |
468
|
|
|
$result = []; |
469
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
470
|
|
|
$metadata = $this->em->getClassMetadata(Country::class); |
471
|
|
|
$key = new QueryCacheKey('query.key1', 0, Cache::MODE_GET); |
472
|
|
|
|
473
|
|
|
$rsm->addRootEntityFromClassMetadata(Country::class, 'c'); |
474
|
|
|
|
475
|
|
View Code Duplication |
for ($i = 0; $i < 4; $i++) { |
|
|
|
|
476
|
|
|
$name = "Country $i"; |
477
|
|
|
$entity = new Country($name); |
478
|
|
|
$result[] = $entity; |
479
|
|
|
|
480
|
|
|
$metadata->setFieldValue($entity, 'id', $i); |
481
|
|
|
$this->em->getUnitOfWork()->registerManaged($entity, ['id' => $i], ['name' => $name]); |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
$this->assertFalse($this->queryCache->put($key, $rsm, $result)); |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
public function testGetShouldIgnoreOldQueryCacheEntryResult() |
488
|
|
|
{ |
489
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
490
|
|
|
$key = new QueryCacheKey('query.key1', 50); |
491
|
|
|
$entry = new QueryCacheEntry( |
492
|
|
|
[ |
493
|
|
|
['identifier' => ['id' => 1]], |
494
|
|
|
['identifier' => ['id' => 2]] |
495
|
|
|
] |
496
|
|
|
); |
497
|
|
|
$entities = [ |
498
|
|
|
['id'=>1, 'name' => 'Foo'], |
499
|
|
|
['id'=>2, 'name' => 'Bar'] |
500
|
|
|
]; |
501
|
|
|
|
502
|
|
|
$entry->time = microtime(true) - 100; |
503
|
|
|
|
504
|
|
|
$this->region->addReturn('get', $entry); |
505
|
|
|
|
506
|
|
|
$this->region->addReturn( |
507
|
|
|
'getMultiple', |
508
|
|
|
[ |
509
|
|
|
new EntityCacheEntry(Country::class, $entities[0]), |
510
|
|
|
new EntityCacheEntry(Country::class, $entities[1]) |
511
|
|
|
] |
512
|
|
|
); |
513
|
|
|
|
514
|
|
|
$rsm->addRootEntityFromClassMetadata(Country::class, 'c'); |
515
|
|
|
|
516
|
|
|
$this->assertNull($this->queryCache->get($key, $rsm)); |
517
|
|
|
} |
518
|
|
|
|
519
|
|
|
public function testGetShouldIgnoreNonQueryCacheEntryResult() |
520
|
|
|
{ |
521
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
522
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
523
|
|
|
$entry = new \ArrayObject( |
524
|
|
|
[ |
525
|
|
|
['identifier' => ['id' => 1]], |
526
|
|
|
['identifier' => ['id' => 2]] |
527
|
|
|
] |
528
|
|
|
); |
529
|
|
|
|
530
|
|
|
$data = [ |
531
|
|
|
['id'=>1, 'name' => 'Foo'], |
532
|
|
|
['id'=>2, 'name' => 'Bar'] |
533
|
|
|
]; |
534
|
|
|
|
535
|
|
|
$this->region->addReturn('get', $entry); |
536
|
|
|
|
537
|
|
|
$this->region->addReturn( |
538
|
|
|
'getMultiple', |
539
|
|
|
[ |
540
|
|
|
new EntityCacheEntry(Country::class, $data[0]), |
541
|
|
|
new EntityCacheEntry(Country::class, $data[1]) |
542
|
|
|
] |
543
|
|
|
); |
544
|
|
|
|
545
|
|
|
$rsm->addRootEntityFromClassMetadata(Country::class, 'c'); |
546
|
|
|
|
547
|
|
|
$this->assertNull($this->queryCache->get($key, $rsm)); |
548
|
|
|
} |
549
|
|
|
|
550
|
|
View Code Duplication |
public function testGetShouldIgnoreMissingEntityQueryCacheEntry() |
551
|
|
|
{ |
552
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
553
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
554
|
|
|
$entry = new QueryCacheEntry( |
555
|
|
|
[ |
556
|
|
|
['identifier' => ['id' => 1]], |
557
|
|
|
['identifier' => ['id' => 2]] |
558
|
|
|
] |
559
|
|
|
); |
560
|
|
|
|
561
|
|
|
$this->region->addReturn('get', $entry); |
562
|
|
|
$this->region->addReturn('getMultiple', [null]); |
563
|
|
|
|
564
|
|
|
$rsm->addRootEntityFromClassMetadata(Country::class, 'c'); |
565
|
|
|
|
566
|
|
|
$this->assertNull($this->queryCache->get($key, $rsm)); |
567
|
|
|
} |
568
|
|
|
|
569
|
|
|
public function testGetAssociationValue() |
570
|
|
|
{ |
571
|
|
|
$reflection = new \ReflectionMethod($this->queryCache, 'getAssociationValue'); |
572
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
573
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
|
|
|
|
574
|
|
|
|
575
|
|
|
$reflection->setAccessible(true); |
576
|
|
|
|
577
|
|
|
$germany = new Country("Germany"); |
578
|
|
|
$bavaria = new State("Bavaria", $germany); |
579
|
|
|
$wurzburg = new City("Würzburg", $bavaria); |
580
|
|
|
$munich = new City("Munich", $bavaria); |
581
|
|
|
|
582
|
|
|
$bavaria->addCity($munich); |
583
|
|
|
$bavaria->addCity($wurzburg); |
584
|
|
|
|
585
|
|
|
$munich->addAttraction(new Restaurant('Reinstoff', $munich)); |
586
|
|
|
$munich->addAttraction(new Restaurant('Schneider Weisse', $munich)); |
587
|
|
|
$wurzburg->addAttraction(new Restaurant('Fischers Fritz', $wurzburg)); |
588
|
|
|
|
589
|
|
|
$rsm->addRootEntityFromClassMetadata(State::class, 's'); |
590
|
|
|
$rsm->addJoinedEntityFromClassMetadata(City::class, 'c', 's', 'cities', [ |
591
|
|
|
'id' => 'c_id', |
592
|
|
|
'name' => 'c_name' |
593
|
|
|
] |
594
|
|
|
); |
595
|
|
|
$rsm->addJoinedEntityFromClassMetadata(Restaurant::class, 'a', 'c', 'attractions', [ |
596
|
|
|
'id' => 'a_id', |
597
|
|
|
'name' => 'a_name' |
598
|
|
|
] |
599
|
|
|
); |
600
|
|
|
|
601
|
|
|
$cities = $reflection->invoke($this->queryCache, $rsm, 'c', $bavaria); |
602
|
|
|
$attractions = $reflection->invoke($this->queryCache, $rsm, 'a', $bavaria); |
603
|
|
|
|
604
|
|
|
$this->assertCount(2, $cities); |
605
|
|
|
$this->assertCount(2, $attractions); |
606
|
|
|
|
607
|
|
|
$this->assertInstanceOf(Collection::class, $cities); |
608
|
|
|
$this->assertInstanceOf(Collection::class, $attractions[0]); |
609
|
|
|
$this->assertInstanceOf(Collection::class, $attractions[1]); |
610
|
|
|
|
611
|
|
|
$this->assertCount(2, $attractions[0]); |
612
|
|
|
$this->assertCount(1, $attractions[1]); |
613
|
|
|
} |
614
|
|
|
|
615
|
|
|
/** |
616
|
|
|
* @expectedException Doctrine\ORM\Cache\CacheException |
617
|
|
|
* @expectedExceptionMessage Second level cache does not support scalar results. |
618
|
|
|
*/ |
619
|
|
|
public function testScalarResultException() |
620
|
|
|
{ |
621
|
|
|
$result = []; |
622
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
623
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
624
|
|
|
|
625
|
|
|
$rsm->addScalarResult('id', 'u', 'integer'); |
626
|
|
|
|
627
|
|
|
$this->queryCache->put($key, $rsm, $result); |
628
|
|
|
} |
629
|
|
|
|
630
|
|
|
/** |
631
|
|
|
* @expectedException Doctrine\ORM\Cache\CacheException |
632
|
|
|
* @expectedExceptionMessage Second level cache does not support multiple root entities. |
633
|
|
|
*/ |
634
|
|
|
public function testSupportMultipleRootEntitiesException() |
635
|
|
|
{ |
636
|
|
|
$result = []; |
637
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
638
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
639
|
|
|
|
640
|
|
|
$rsm->addEntityResult(City::class, 'e1'); |
641
|
|
|
$rsm->addEntityResult(State::class, 'e2'); |
642
|
|
|
|
643
|
|
|
$this->queryCache->put($key, $rsm, $result); |
644
|
|
|
} |
645
|
|
|
|
646
|
|
|
/** |
647
|
|
|
* @expectedException Doctrine\ORM\Cache\CacheException |
648
|
|
|
* @expectedExceptionMessage Entity "Doctrine\Tests\Models\Generic\BooleanModel" not configured as part of the second-level cache. |
649
|
|
|
*/ |
650
|
|
|
public function testNotCacheableEntityException() |
651
|
|
|
{ |
652
|
|
|
$result = []; |
653
|
|
|
$key = new QueryCacheKey('query.key1', 0); |
654
|
|
|
$rsm = new ResultSetMappingBuilder($this->em); |
655
|
|
|
$rsm->addRootEntityFromClassMetadata(BooleanModel::class, 'c'); |
656
|
|
|
|
657
|
|
|
for ($i = 0; $i < 4; $i++) { |
658
|
|
|
$entity = new BooleanModel(); |
659
|
|
|
$boolean = ($i % 2 === 0); |
660
|
|
|
|
661
|
|
|
$entity->id = $i; |
662
|
|
|
$entity->booleanField = $boolean; |
663
|
|
|
$result[] = $entity; |
664
|
|
|
|
665
|
|
|
$this->em->getUnitOfWork()->registerManaged($entity, ['id' => $i], ['booleanField' => $boolean]); |
666
|
|
|
} |
667
|
|
|
|
668
|
|
|
$this->assertFalse($this->queryCache->put($key, $rsm, $result)); |
669
|
|
|
} |
670
|
|
|
|
671
|
|
|
} |
672
|
|
|
|
673
|
|
|
class CacheFactoryDefaultQueryCacheTest extends Cache\DefaultCacheFactory |
674
|
|
|
{ |
675
|
|
|
private $queryCache; |
676
|
|
|
private $region; |
677
|
|
|
|
678
|
|
|
public function __construct(DefaultQueryCache $queryCache, CacheRegionMock $region) |
679
|
|
|
{ |
680
|
|
|
$this->queryCache = $queryCache; |
681
|
|
|
$this->region = $region; |
682
|
|
|
} |
683
|
|
|
|
684
|
|
|
public function buildQueryCache(EntityManagerInterface $em, $regionName = null) |
685
|
|
|
{ |
686
|
|
|
return $this->queryCache; |
687
|
|
|
} |
688
|
|
|
|
689
|
|
|
public function getRegion(array $cache) |
690
|
|
|
{ |
691
|
|
|
return $this->region; |
692
|
|
|
} |
693
|
|
|
|
694
|
|
|
public function getTimestampRegion() |
695
|
|
|
{ |
696
|
|
|
return new TimestampRegionMock(); |
697
|
|
|
} |
698
|
|
|
} |
699
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.