Ticket #1277 (closed defect: fixed)
Unexpected behaviours when record is first queried partially and later fully
| Reported by: | margus | Owned by: | romanb |
|---|---|---|---|
| Priority: | major | Milestone: | |
| Component: | Record | Version: | 1.0.0 |
| Severity: | Keywords: | ||
| Cc: | Has Test: | no | |
| Status: | Pending Core Response | Has Patch: | no |
Description
Doctrine keeps all records internally in his identity map (in Doctrine_Table). So when I fetch the same record twice, second time it actually returns me the instance of record which was fetched in the first time. Record's state on the other hand will not be updated from PROXY to persistent CLEAN or persistent DIRTY. This results in unexpected behaviours.
// This is the User table where I have 2 records:
// ID USERNAME EMAIL
// #1 User1 NULL
// #2 User2 some@email
class User extends Doctrine_Record
{
public function setTableDefinition ()
{
$this->setTableName("users");
$this->hasColumns (array(
'id' => array(
'type' => 'integer',
'notnull' => true,
'autoincrement' => true,
'primary' => true
),
'username' => array(
'type' => 'string',
),
'email' => array(
'type' => 'string',
'default' => null,
),
));
}
}
I will query this table first time somewhere in the code:
$q = new Doctrine_Query();
$u = $q->select('u.id')->from ('User u')->where ('u.id=1')->fetchOne ();
echo 'User#' . $u->id . ' state=' . Doctrine_Lib::getRecordStateAsString ($u->state ()) . "<br />
";
// This prints:
// User#1 state=proxy
In some other part of code I will query this table again and start making modifications to found records:
$q = new Doctrine_Query();
$users = $q->select('u.*')->from ('User u')->execute ();
foreach ($users as $u) {
echo 'User#' . $u->id . ' state=' . Doctrine_Lib::getRecordStateAsString ($u->state ()) . "<br />
";
$u->username = 'new username' . $u->id;
$u->email = 'some' . $u->id . '@email';
echo 'User#' . $u->id . ' username=' . $u->username . "<br />
";
}
// This prints:
// User#1 state=proxy
// User#1 username=user1
// User#2 state=persistent clean
// User#2 username=new username2
As you see:
- UserID=1 stays in PROXY state even if all the attributes have been fetched from database
- UserID=2 get's his username updated to "new username2" but UserID=1 get's not. This is because UserID=1 has his email set to NULL and Doctrine refreshes the whole record transparently if it detects that the record is in PROXY state and an attribute with NULL value get's updated.
- The code above causes actually 3 database queries instead of 2 which is expected if you look at the code.
Change History
Note: See
TracTickets for help on using
tickets.