#1581: [PATCH] Doctrine_Connection_UnitOfWork::buildFlushTree() removes wrong
objects by accident
-------------------------+--------------------------------------------------
Reporter: bschussek | Owner: jwage
Type: defect | Status: closed
Priority: critical | Milestone:
Component: Connection | Version: 0.11.0
Resolution: invalid | Keywords:
Has_test: 0 | Mystatus: Pending Core Response
Has_patch: 1 |
-------------------------+--------------------------------------------------
Changes (by jwage):
* status: new => closed
* resolution: => invalid
Old description:
> When loading fixture files, Doctrine uses
> Doctrine_Connection_UnitOfWork::buildFlushTree() to find out in which
> order the fixture classes should be saved. Therefore the classes are
> given to the method and returned in the correct order.
>
> In certain situations, some of the classes that were put in are not put
> out, leading to fixture entries not being loaded into the database. I
> didn't really find out WHEN this happens, but I found out WHY and created
> a patch for it.
>
> The algorithm in buildFlushTree() uses unset() a couple of times to
> remove an object and add it at the end of the object. Example (line 725):
> {{{
> if ($relatedCompIndex !== false) {
> unset($flushList[$relatedCompIndex]);
> }
>
> array_splice($flushList, $index, 0,
> $relatedClassName);
> $index++;
> }}}
>
> Through the use of unset, the array keys have "holes" (1, 2, 4, ...
> instead of 1, 2, 3, ...). Now the critical part: array_splice() closes
> these holes (=alters the indices from 1, 2, 4,... to 1, 2, 3, ...), which
> is why $index is not correct anymore afterwards! Doctrine uses the $index
> later though, which can lead to wrong objects being removed! (e.g. in
> line 740, which is what happens in my case)
>
> A working solution for me is to replace all calls to array_splice() with
> calls to a custom method _arrayInsert(), which preserves the keys:
> {{{
> private function _arrayInsert($array, $index, $data)
> {
> for ($j=max(array_keys($array)); $j>=$index; --$j)
> {
> $array[$j+1] = $array[$j];
> }
>
> $array[$index] = $data;
>
> return $array;
> }
> }}}
New description:
When loading fixture files, Doctrine uses
Doctrine_Connection_UnitOfWork::buildFlushTree() to find out in which
order the fixture classes should be saved. Therefore the classes are given
to the method and returned in the correct order.
In certain situations, some of the classes that were put in are not put
out, leading to fixture entries not being loaded into the database. I
didn't really find out WHEN this happens, but I found out WHY and created
a patch for it.
The algorithm in buildFlushTree() uses unset() a couple of times to remove
an object and add it at the end of the object. Example (line 725):
{{{
if ($relatedCompIndex !== false) {
unset($flushList[$relatedCompIndex]);
}
array_splice($flushList, $index, 0,
$relatedClassName);
$index++;
}}}
Through the use of unset, the array keys have "holes" (1, 2, 4, ...
instead of 1, 2, 3, ...). Now the critical part: array_splice() closes
these holes (=alters the indices from 1, 2, 4,... to 1, 2, 3, ...), which
is why $index is not correct anymore afterwards! Doctrine uses the $index
later though, which can lead to wrong objects being removed! (e.g. in line
740, which is what happens in my case)
A working solution for me is to replace all calls to array_splice() with
calls to a custom method _arrayInsert(), which preserves the keys:
{{{
private function _arrayInsert($array, $index, $data)
{
for ($j=max(array_keys($array)); $j>=$index; --$j)
{
$array[$j+1] = $array[$j];
}
$array[$index] = $data;
return $array;
}
}}}
--
Ticket URL: <http://trac.doctrine-project.org/ticket/1581#comment:6>
Doctrine <http://www.phpdoctrine.org>
PHP Doctrine Object Relational Mapper
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"doctrine-svn" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.co.uk/group/doctrine-svn?hl=en-GB
-~----------~----~----~----~------~----~------~--~---