Ticket #1277 (closed defect: fixed)

Opened 12 months ago

Last modified 10 months ago

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

Changed 11 months ago by jwage

  • version changed from 0.11 to 1.0
  • milestone changed from Unknown to 1.0.0-RC1

Changed 11 months ago by romanb

  • status changed from new to assigned

Changed 11 months ago by romanb

  • status changed from assigned to closed
  • resolution set to fixed

(In [4772]) Fixed #1277. Added coverage for #1254.

Changed 10 months ago by anonymous

  • milestone New deleted

Milestone New deleted

Note: See TracTickets for help on using tickets.