1
0
mirror of synced 2024-12-13 14:56:01 +03:00

fast identifier search for Doctrine_Hydrate, now the hydration should run in O(1) instead of O(n)

This commit is contained in:
zYne 2007-10-22 16:38:03 +00:00
parent 6ed2e63d88
commit a01ed0641f
4 changed files with 57 additions and 29 deletions

View File

@ -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

View File

@ -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();

View File

@ -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()
{ {
} }
} }

View File

@ -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)
{ {