fast identifier search for Doctrine_Hydrate, now the hydration should run in O(1) instead of O(n)
This commit is contained in:
parent
6ed2e63d88
commit
a01ed0641f
@ -235,7 +235,24 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
|
||||
{
|
||||
return end($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the last record in the collection
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function end()
|
||||
{
|
||||
return end($this->data);
|
||||
}
|
||||
/**
|
||||
* returns the current key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return key($this->data);
|
||||
}
|
||||
/**
|
||||
* setReference
|
||||
* sets a reference pointer
|
||||
|
@ -1059,6 +1059,10 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
||||
foreach ($this->_aliasMap as $alias => $data) {
|
||||
$componentName = $data['table']->getComponentName();
|
||||
$listeners[$componentName] = $data['table']->getRecordListener();
|
||||
$identifierMap[$alias] = array();
|
||||
$currData[$alias] = array();
|
||||
$prev[$alias] = array();
|
||||
$id[$alias] = '';
|
||||
}
|
||||
|
||||
while ($data = $stmt->fetch(Doctrine::FETCH_ASSOC)) {
|
||||
@ -1076,7 +1080,6 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
||||
$cache[$key]['alias'] = $this->_tableAliases[strtolower(implode('__', $e))];
|
||||
}
|
||||
|
||||
|
||||
$map = $this->_aliasMap[$cache[$key]['alias']];
|
||||
$table = $map['table'];
|
||||
$alias = $cache[$key]['alias'];
|
||||
@ -1087,21 +1090,17 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
||||
}
|
||||
|
||||
|
||||
if ( ! isset($currData[$alias])) {
|
||||
$currData[$alias] = array();
|
||||
}
|
||||
|
||||
if ( ! isset($prev[$alias])) {
|
||||
$prev[$alias] = array();
|
||||
if ($table->isIdentifier($field)) {
|
||||
$id[$alias] .= '|' . $value;
|
||||
}
|
||||
|
||||
$currData[$alias][$field] = $table->prepareValue($field, $value);
|
||||
|
||||
if ($value !== null) {
|
||||
$identifiable[$alias] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// dealing with root component
|
||||
$table = $this->_aliasMap[$rootAlias]['table'];
|
||||
$componentName = $table->getComponentName();
|
||||
@ -1111,8 +1110,13 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
||||
|
||||
$oneToOne = false;
|
||||
|
||||
$index = $isSimpleQuery ? false : $driver->search($element, $array);
|
||||
|
||||
if ($isSimpleQuery) {
|
||||
$index = false;
|
||||
} else {
|
||||
$index = isset($identifierMap[$rootAlias][$id[$rootAlias]]) ?
|
||||
$identifierMap[$rootAlias][$id[$rootAlias]] : false;
|
||||
}
|
||||
|
||||
if ($index === false) {
|
||||
$event->set('data', $element);
|
||||
$listeners[$componentName]->postHydrate($event);
|
||||
@ -1132,7 +1136,10 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
||||
} else {
|
||||
$array[] = $element;
|
||||
}
|
||||
|
||||
$identifierMap[$rootAlias][$id[$rootAlias]] = $driver->getLastKey($array);
|
||||
}
|
||||
|
||||
$this->_setLastElement($prev, $array, $index, $rootAlias, $oneToOne);
|
||||
unset($currData[$rootAlias]);
|
||||
|
||||
@ -1150,6 +1157,8 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
||||
$relation = $map['relation'];
|
||||
$componentAlias = $map['relation']->getAlias();
|
||||
|
||||
$path = $parent . '.' . $alias;
|
||||
|
||||
if ( ! isset($prev[$parent])) {
|
||||
break;
|
||||
}
|
||||
@ -1162,7 +1171,12 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
||||
|
||||
// append element
|
||||
if (isset($identifiable[$alias])) {
|
||||
$index = $isSimpleQuery ? false : $driver->search($element, $prev[$parent][$componentAlias]);
|
||||
if ($isSimpleQuery) {
|
||||
$index = false;
|
||||
} else {
|
||||
$index = isset($identifierMap[$path][$id[$parent]][$id[$alias]]) ?
|
||||
$identifierMap[$path][$id[$parent]][$id[$alias]] : false;
|
||||
}
|
||||
|
||||
if ($index === false) {
|
||||
$event->set('data', $element);
|
||||
@ -1180,6 +1194,8 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
||||
} else {
|
||||
$prev[$parent][$componentAlias][] = $element;
|
||||
}
|
||||
|
||||
$identifierMap[$path][$id[$parent]][$id[$alias]] = $driver->getLastKey($prev[$parent][$componentAlias]);
|
||||
}
|
||||
}
|
||||
// register collection for later snapshots
|
||||
@ -1195,7 +1211,9 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
||||
}
|
||||
$coll =& $prev[$parent][$componentAlias];
|
||||
$this->_setLastElement($prev, $coll, $index, $alias, $oneToOne);
|
||||
$id[$alias] = '';
|
||||
}
|
||||
$id[$rootAlias] = '';
|
||||
}
|
||||
|
||||
$driver->flush();
|
||||
|
@ -60,24 +60,14 @@ class Doctrine_Hydrate_Array
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public function search(array $element, array $data)
|
||||
public function getLastKey(&$data)
|
||||
{
|
||||
foreach ($data as $key => $val) {
|
||||
$found = true;
|
||||
foreach ($element as $k => $e) {
|
||||
if (isset($val[$k]) && $val[$k] !== $e) {
|
||||
$found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($found) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
end($data);
|
||||
return key($data);
|
||||
}
|
||||
|
||||
public function flush()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,9 +46,12 @@ class Doctrine_Hydrate_Record extends Doctrine_Locator_Injectable
|
||||
|
||||
return $coll;
|
||||
}
|
||||
public function search(Doctrine_Record $record, Doctrine_Collection $coll)
|
||||
|
||||
public function getLastKey($coll)
|
||||
{
|
||||
return array_search($record, $coll->getData(), true);
|
||||
$coll->end();
|
||||
|
||||
return $coll->key();
|
||||
}
|
||||
public function initRelated($record, $name)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user