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);
|
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
|
* setReference
|
||||||
* sets a reference pointer
|
* sets a reference pointer
|
||||||
|
@ -1059,6 +1059,10 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
|||||||
foreach ($this->_aliasMap as $alias => $data) {
|
foreach ($this->_aliasMap as $alias => $data) {
|
||||||
$componentName = $data['table']->getComponentName();
|
$componentName = $data['table']->getComponentName();
|
||||||
$listeners[$componentName] = $data['table']->getRecordListener();
|
$listeners[$componentName] = $data['table']->getRecordListener();
|
||||||
|
$identifierMap[$alias] = array();
|
||||||
|
$currData[$alias] = array();
|
||||||
|
$prev[$alias] = array();
|
||||||
|
$id[$alias] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
while ($data = $stmt->fetch(Doctrine::FETCH_ASSOC)) {
|
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))];
|
$cache[$key]['alias'] = $this->_tableAliases[strtolower(implode('__', $e))];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$map = $this->_aliasMap[$cache[$key]['alias']];
|
$map = $this->_aliasMap[$cache[$key]['alias']];
|
||||||
$table = $map['table'];
|
$table = $map['table'];
|
||||||
$alias = $cache[$key]['alias'];
|
$alias = $cache[$key]['alias'];
|
||||||
@ -1087,21 +1090,17 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( ! isset($currData[$alias])) {
|
if ($table->isIdentifier($field)) {
|
||||||
$currData[$alias] = array();
|
$id[$alias] .= '|' . $value;
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! isset($prev[$alias])) {
|
|
||||||
$prev[$alias] = array();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$currData[$alias][$field] = $table->prepareValue($field, $value);
|
$currData[$alias][$field] = $table->prepareValue($field, $value);
|
||||||
|
|
||||||
if ($value !== null) {
|
if ($value !== null) {
|
||||||
$identifiable[$alias] = true;
|
$identifiable[$alias] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// dealing with root component
|
// dealing with root component
|
||||||
$table = $this->_aliasMap[$rootAlias]['table'];
|
$table = $this->_aliasMap[$rootAlias]['table'];
|
||||||
$componentName = $table->getComponentName();
|
$componentName = $table->getComponentName();
|
||||||
@ -1111,8 +1110,13 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
|||||||
|
|
||||||
$oneToOne = false;
|
$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) {
|
if ($index === false) {
|
||||||
$event->set('data', $element);
|
$event->set('data', $element);
|
||||||
$listeners[$componentName]->postHydrate($event);
|
$listeners[$componentName]->postHydrate($event);
|
||||||
@ -1132,7 +1136,10 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
|||||||
} else {
|
} else {
|
||||||
$array[] = $element;
|
$array[] = $element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$identifierMap[$rootAlias][$id[$rootAlias]] = $driver->getLastKey($array);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_setLastElement($prev, $array, $index, $rootAlias, $oneToOne);
|
$this->_setLastElement($prev, $array, $index, $rootAlias, $oneToOne);
|
||||||
unset($currData[$rootAlias]);
|
unset($currData[$rootAlias]);
|
||||||
|
|
||||||
@ -1150,6 +1157,8 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
|||||||
$relation = $map['relation'];
|
$relation = $map['relation'];
|
||||||
$componentAlias = $map['relation']->getAlias();
|
$componentAlias = $map['relation']->getAlias();
|
||||||
|
|
||||||
|
$path = $parent . '.' . $alias;
|
||||||
|
|
||||||
if ( ! isset($prev[$parent])) {
|
if ( ! isset($prev[$parent])) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1162,7 +1171,12 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
|||||||
|
|
||||||
// append element
|
// append element
|
||||||
if (isset($identifiable[$alias])) {
|
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) {
|
if ($index === false) {
|
||||||
$event->set('data', $element);
|
$event->set('data', $element);
|
||||||
@ -1180,6 +1194,8 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
|||||||
} else {
|
} else {
|
||||||
$prev[$parent][$componentAlias][] = $element;
|
$prev[$parent][$componentAlias][] = $element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$identifierMap[$path][$id[$parent]][$id[$alias]] = $driver->getLastKey($prev[$parent][$componentAlias]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// register collection for later snapshots
|
// register collection for later snapshots
|
||||||
@ -1195,7 +1211,9 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
|
|||||||
}
|
}
|
||||||
$coll =& $prev[$parent][$componentAlias];
|
$coll =& $prev[$parent][$componentAlias];
|
||||||
$this->_setLastElement($prev, $coll, $index, $alias, $oneToOne);
|
$this->_setLastElement($prev, $coll, $index, $alias, $oneToOne);
|
||||||
|
$id[$alias] = '';
|
||||||
}
|
}
|
||||||
|
$id[$rootAlias] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$driver->flush();
|
$driver->flush();
|
||||||
|
@ -60,24 +60,14 @@ class Doctrine_Hydrate_Array
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public function search(array $element, array $data)
|
public function getLastKey(&$data)
|
||||||
{
|
{
|
||||||
foreach ($data as $key => $val) {
|
end($data);
|
||||||
$found = true;
|
return key($data);
|
||||||
foreach ($element as $k => $e) {
|
|
||||||
if (isset($val[$k]) && $val[$k] !== $e) {
|
|
||||||
$found = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($found) {
|
|
||||||
return $key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function flush()
|
public function flush()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,12 @@ class Doctrine_Hydrate_Record extends Doctrine_Locator_Injectable
|
|||||||
|
|
||||||
return $coll;
|
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)
|
public function initRelated($record, $name)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user