Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 81cc6d9

Browse files
Implemented alias support for EntityResult. This addresses DDC-1096 and DDC-1424. Improved DQL Parser, SQL Walker and Hydrators in general. Performance is generally improved by a factor of 20%. There is still more to be done, like remove the isMixed in ResultSetMapping, mainly because this query - SELECT u AS user FROM User u -, it should return an array('user' => [User object]), while currently it doesn't due to this before mentioned 'bug' in RSM. Will open a separate ticket for this. Also, UnitOfWork and Hydrators share code that could be abstracted/improved.
1 parent e8eda4a commit 81cc6d9

9 files changed

Lines changed: 1433 additions & 1146 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ download/
77
lib/api/
88
lib/Doctrine/Common
99
lib/Doctrine/DBAL
10+
/.settings/
11+
.buildpath
12+
.project

lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php

Lines changed: 96 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,17 @@ public function __construct(EntityManager $em)
7474
*
7575
* @param object $stmt
7676
* @param object $resultSetMapping
77-
*
77+
*
7878
* @return IterableResult
7979
*/
8080
public function iterate($stmt, $resultSetMapping, array $hints = array())
8181
{
8282
$this->_stmt = $stmt;
8383
$this->_rsm = $resultSetMapping;
8484
$this->_hints = $hints;
85-
85+
8686
$this->prepare();
87-
87+
8888
return new IterableResult($this);
8989
}
9090

@@ -100,13 +100,13 @@ public function hydrateAll($stmt, $resultSetMapping, array $hints = array())
100100
$this->_stmt = $stmt;
101101
$this->_rsm = $resultSetMapping;
102102
$this->_hints = $hints;
103-
103+
104104
$this->prepare();
105-
105+
106106
$result = $this->hydrateAllData();
107-
107+
108108
$this->cleanup();
109-
109+
110110
return $result;
111111
}
112112

@@ -119,17 +119,17 @@ public function hydrateAll($stmt, $resultSetMapping, array $hints = array())
119119
public function hydrateRow()
120120
{
121121
$row = $this->_stmt->fetch(PDO::FETCH_ASSOC);
122-
122+
123123
if ( ! $row) {
124124
$this->cleanup();
125-
125+
126126
return false;
127127
}
128-
128+
129129
$result = array();
130-
130+
131131
$this->hydrateRowData($row, $this->_cache, $result);
132-
132+
133133
return $result;
134134
}
135135

@@ -147,7 +147,7 @@ protected function prepare()
147147
protected function cleanup()
148148
{
149149
$this->_rsm = null;
150-
150+
151151
$this->_stmt->closeCursor();
152152
$this->_stmt = null;
153153
}
@@ -195,34 +195,44 @@ protected function gatherRowData(array $data, array &$cache, array &$id, array &
195195
foreach ($data as $key => $value) {
196196
// Parse each column name only once. Cache the results.
197197
if ( ! isset($cache[$key])) {
198-
if (isset($this->_rsm->scalarMappings[$key])) {
199-
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
200-
$cache[$key]['isScalar'] = true;
201-
} else if (isset($this->_rsm->fieldMappings[$key])) {
202-
$fieldName = $this->_rsm->fieldMappings[$key];
203-
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
204-
$cache[$key]['fieldName'] = $fieldName;
205-
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
206-
$cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
207-
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
208-
} else if (!isset($this->_rsm->metaMappings[$key])) {
209-
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
210-
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
211-
continue;
212-
} else {
213-
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
214-
$fieldName = $this->_rsm->metaMappings[$key];
215-
$cache[$key]['isMetaColumn'] = true;
216-
$cache[$key]['fieldName'] = $fieldName;
217-
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
218-
$classMetadata = $this->_em->getClassMetadata($this->_rsm->aliasMap[$cache[$key]['dqlAlias']]);
219-
$cache[$key]['isIdentifier'] = isset($this->_rsm->isIdentifierColumn[$cache[$key]['dqlAlias']][$key]);
198+
switch (true) {
199+
// NOTE: Most of the times it's a field mapping, so keep it first!!!
200+
case (isset($this->_rsm->fieldMappings[$key])):
201+
$fieldName = $this->_rsm->fieldMappings[$key];
202+
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
203+
204+
$cache[$key]['fieldName'] = $fieldName;
205+
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
206+
$cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
207+
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
208+
break;
209+
210+
case (isset($this->_rsm->scalarMappings[$key])):
211+
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
212+
$cache[$key]['isScalar'] = true;
213+
break;
214+
215+
case (isset($this->_rsm->metaMappings[$key])):
216+
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
217+
$fieldName = $this->_rsm->metaMappings[$key];
218+
$classMetadata = $this->_em->getClassMetadata($this->_rsm->aliasMap[$this->_rsm->columnOwnerMap[$key]]);
219+
220+
$cache[$key]['isMetaColumn'] = true;
221+
$cache[$key]['fieldName'] = $fieldName;
222+
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
223+
$cache[$key]['isIdentifier'] = isset($this->_rsm->isIdentifierColumn[$cache[$key]['dqlAlias']][$key]);
224+
break;
225+
226+
default:
227+
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
228+
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
229+
continue 2;
220230
}
221231
}
222232

223233
if (isset($cache[$key]['isScalar'])) {
224234
$rowData['scalars'][$cache[$key]['fieldName']] = $value;
225-
235+
226236
continue;
227237
}
228238

@@ -233,10 +243,10 @@ protected function gatherRowData(array $data, array &$cache, array &$id, array &
233243
}
234244

235245
if (isset($cache[$key]['isMetaColumn'])) {
236-
if (!isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) || $value !== null) {
246+
if ( ! isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) || $value !== null) {
237247
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $value;
238248
}
239-
249+
240250
continue;
241251
}
242252

@@ -259,15 +269,15 @@ protected function gatherRowData(array $data, array &$cache, array &$id, array &
259269

260270
/**
261271
* Processes a row of the result set.
262-
*
272+
*
263273
* Used for HYDRATE_SCALAR. This is a variant of _gatherRowData() that
264274
* simply converts column names to field names and properly converts the
265275
* values according to their types. The resulting row has the same number
266276
* of elements as before.
267277
*
268278
* @param array $data
269279
* @param array $cache
270-
*
280+
*
271281
* @return array The processed row.
272282
*/
273283
protected function gatherScalarRowData(&$data, &$cache)
@@ -277,48 +287,65 @@ protected function gatherScalarRowData(&$data, &$cache)
277287
foreach ($data as $key => $value) {
278288
// Parse each column name only once. Cache the results.
279289
if ( ! isset($cache[$key])) {
280-
if (isset($this->_rsm->scalarMappings[$key])) {
281-
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
282-
$cache[$key]['isScalar'] = true;
283-
} else if (isset($this->_rsm->fieldMappings[$key])) {
284-
$fieldName = $this->_rsm->fieldMappings[$key];
285-
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
286-
$cache[$key]['fieldName'] = $fieldName;
287-
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
288-
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
289-
} else if (!isset($this->_rsm->metaMappings[$key])) {
290-
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
291-
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
292-
continue;
293-
} else {
294-
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
295-
$cache[$key]['isMetaColumn'] = true;
296-
$cache[$key]['fieldName'] = $this->_rsm->metaMappings[$key];
297-
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
290+
switch (true) {
291+
// NOTE: During scalar hydration, most of the times it's a scalar mapping, keep it first!!!
292+
case (isset($this->_rsm->scalarMappings[$key])):
293+
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
294+
$cache[$key]['isScalar'] = true;
295+
break;
296+
297+
case (isset($this->_rsm->fieldMappings[$key])):
298+
$fieldName = $this->_rsm->fieldMappings[$key];
299+
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
300+
301+
$cache[$key]['fieldName'] = $fieldName;
302+
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
303+
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
304+
break;
305+
306+
case (isset($this->_rsm->metaMappings[$key])):
307+
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
308+
$cache[$key]['isMetaColumn'] = true;
309+
$cache[$key]['fieldName'] = $this->_rsm->metaMappings[$key];
310+
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
311+
break;
312+
313+
default:
314+
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
315+
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
316+
continue 2;
298317
}
299318
}
300319

301320
$fieldName = $cache[$key]['fieldName'];
302321

303-
if (isset($cache[$key]['isScalar'])) {
304-
$rowData[$fieldName] = $value;
305-
} else if (isset($cache[$key]['isMetaColumn'])) {
306-
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $value;
307-
} else {
308-
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $cache[$key]['type']
309-
->convertToPHPValue($value, $this->_platform);
322+
switch (true) {
323+
case (isset($cache[$key]['isScalar'])):
324+
$rowData[$fieldName] = $value;
325+
break;
326+
327+
case (isset($cache[$key]['isMetaColumn'])):
328+
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $value;
329+
break;
330+
331+
default:
332+
$value = $cache[$key]['type']->convertToPHPValue($value, $this->_platform);
333+
334+
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $value;
310335
}
311336
}
312337

313338
return $rowData;
314339
}
315-
340+
316341
/**
317342
* Register entity as managed in UnitOfWork.
318-
*
343+
*
319344
* @param Doctrine\ORM\Mapping\ClassMetadata $class
320345
* @param object $entity
321-
* @param array $data
346+
* @param array $data
347+
*
348+
* @todo The "$id" generation is the same of UnitOfWork#createEntity. Remove this duplication somehow
322349
*/
323350
protected function registerManaged(ClassMetadata $class, $entity, array $data)
324351
{
@@ -338,7 +365,7 @@ protected function registerManaged(ClassMetadata $class, $entity, array $data)
338365
$id = array($class->identifier[0] => $data[$class->identifier[0]]);
339366
}
340367
}
341-
368+
342369
$this->_em->getUnitOfWork()->registerManaged($entity, $id, $data);
343370
}
344371
}

0 commit comments

Comments
 (0)