Uploaded image for project: 'Doctrine 1'
  1. Doctrine 1
  2. DC-1050

Doctrine_Relation_ForeignKey ignores ATTR_COLL_KEY attribute

    Details

    • Type: Bug
    • Status: Open
    • Priority: Critical
    • Resolution: Unresolved
    • Affects Version/s: 1.2.3
    • Fix Version/s: None
    • Component/s: Attributes, Relations
    • Labels:
      None
    • Environment:
      Windows 7 64Bit
      PHP 5.3
      Symfony 1.4

      Description

      Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

      $coll = $this->getTable()>getConnection()>query($dql, $id);
      $related = $coll[0];

      As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

      $this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

      Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

      // program 1:

      $m = new Main();
      $m->name = 'M1';
      $m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
      $m->setForeignB(new ForeignB());
      $m->save();

      // program 2:

      $m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
      $m->getForeignA()->exists(); // false
      $m->getForeignB()->exists(); // true

      -------------------------

      The big problem about this issue is that behavior is inconsistent. If you don't split the example above into two separate programs/processes you won't have problems, since Doctrine accesses the reference which was stored when calling save().

      You will get into trouble using functional tests in Symfony. Since there is only a single process for all requests I wasn't able to reproduce a problem caused by this bug which appeared in the production environment.

      -------------------------

      Edit:

      Doctrine_Connection::queryOne() is affected as well!

      A solution is to replace

      $coll = $this->getTable()>getConnection()>query($dql, $id);
      $related = $coll[0];

      by

      $related = $this->getTable()>getConnection()>query($dql, $id)->getFirst();

      1. ForeignKey.php.patch
        0.6 kB
        Uli Hecht
      2. Form01 - Diagnóstico-12012011.doc
        140 kB
        joao guermandi
      3. Proposta do sistema de Gestão de ligas.odt
        19 kB
        joao guermandi
      4. Proposta do sistema de meio ambiente.odt
        19 kB
        joao guermandi

        Activity

        fishbone Uli Hecht created issue -
        fishbone Uli Hecht made changes -
        Field Original Value New Value
        Description Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

        $coll = $this->getTable()->getConnection()->query($dql, $id);
        $related = $coll[0];

        As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

        $this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

        Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

        // program 1:

        $m = new Main();
        $m->name = 'M1';
        $m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
        $m->setForeignB(new ForeignB());
        $m->save();

        // program 2:

        $m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
        $m->getForeignA()->exists(); // false
        $m->getForeignB()->exists(); // true

        -------------------------

        Now consider you run functional tests in a Symfony project: The problem disappears since you only have a single sfContext for multiple requests. I.e. this issue causes an inconsistent behavior. This is why I wrote "program 1" and "program 2" above.
        Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

        $coll = $this->getTable()->getConnection()->query($dql, $id);
        $related = $coll[0];

        As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

        $this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

        Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

        // program 1:

        $m = new Main();
        $m->name = 'M1';
        $m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
        $m->setForeignB(new ForeignB());
        $m->save();

        // program 2:

        $m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
        $m->getForeignA()->exists(); // false
        $m->getForeignB()->exists(); // true

        -------------------------

        The big problem about this issue is that behavior is inconsistent. If you don't split the example above into two separate programs/processes you won't have problems, since Doctrine accesses the reference which was stored when calling save().

        You will get into trouble using functional tests in Symfony. Since there is only a single process for all requests I wasn't able to reproduce a problem caused by this bug which appeared in the production environment.

        -------------------------

        Edit:

        Doctrine_Connection is affected as well.

        A solution is to replace
        fishbone Uli Hecht made changes -
        Description Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

        $coll = $this->getTable()->getConnection()->query($dql, $id);
        $related = $coll[0];

        As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

        $this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

        Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

        // program 1:

        $m = new Main();
        $m->name = 'M1';
        $m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
        $m->setForeignB(new ForeignB());
        $m->save();

        // program 2:

        $m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
        $m->getForeignA()->exists(); // false
        $m->getForeignB()->exists(); // true

        -------------------------

        The big problem about this issue is that behavior is inconsistent. If you don't split the example above into two separate programs/processes you won't have problems, since Doctrine accesses the reference which was stored when calling save().

        You will get into trouble using functional tests in Symfony. Since there is only a single process for all requests I wasn't able to reproduce a problem caused by this bug which appeared in the production environment.

        -------------------------

        Edit:

        Doctrine_Connection is affected as well.

        A solution is to replace
        Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

        $coll = $this->getTable()->getConnection()->query($dql, $id);
        $related = $coll[0];

        As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

        $this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

        Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

        // program 1:

        $m = new Main();
        $m->name = 'M1';
        $m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
        $m->setForeignB(new ForeignB());
        $m->save();

        // program 2:

        $m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
        $m->getForeignA()->exists(); // false
        $m->getForeignB()->exists(); // true

        -------------------------

        The big problem about this issue is that behavior is inconsistent. If you don't split the example above into two separate programs/processes you won't have problems, since Doctrine accesses the reference which was stored when calling save().

        You will get into trouble using functional tests in Symfony. Since there is only a single process for all requests I wasn't able to reproduce a problem caused by this bug which appeared in the production environment.

        -------------------------

        Edit:

        Doctrine_Connection::queryOne() is affected as well!

        A solution is to replace

        $coll = $this->getTable()->getConnection()->query($dql, $id);
        $related = $coll[0];

        by

        $related = $this->getTable()->getConnection()->query($dql, $id)->getFirst();
        Hide
        fishbone Uli Hecht added a comment -

        Suggested patch

        Show
        fishbone Uli Hecht added a comment - Suggested patch
        fishbone Uli Hecht made changes -
        Attachment ForeignKey.php.patch [ 11167 ]
        guilhermeblanco Guilherme Blanco made changes -
        Fix Version/s 1.2.4 [ 10063 ]
        Hide
        joaoisobr joao guermandi added a comment -

        Implementação

        Show
        joaoisobr joao guermandi added a comment - Implementação
        joaoisobr joao guermandi made changes -

        This list may be incomplete, as errors occurred whilst retrieving source from linked applications:

        • Request to http://www.doctrine-project.org/fisheye/ failed: Error in remote call to 'FishEye 0 (http://www.doctrine-project.org/fisheye/)' (http://www.doctrine-project.org/fisheye) [AbstractRestCommand{path='/rest-service-fe/search-v1/crossRepositoryQuery', params={expand=changesets[0:20].revisions[0:29],reviews, query=DC-1050}, methodType=GET}] : Received status code 503 (Service Temporarily Unavailable)

          People

          • Assignee:
            jwage Jonathan H. Wage
            Reporter:
            fishbone Uli Hecht
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: