Doctrine 1
  1. Doctrine 1
  2. DC-553

issue when changing the connection inside Doctrine_Query::preQuery() on a model using a behavior

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: 1.2.1
    • Component/s: Behaviors
    • Labels:
      None

      Description

      We were following:
      http://www.doctrine-project.org/documentation/cookbook/1_1/en/master-and-slave-connections

      class MyQuery extends Doctrine_Query
      {
      // Since php doesn't support late static binding in 5.2 we need to override
      // this method to instantiate a new MyQuery instead of Doctrine_Query
      public static function create($conn = null)

      { return new MyQuery($conn); }

      public function preQuery()
      {
      // If this is a select query then set connection to one of the slaves
      if ($this->getType() == Doctrine_Query::SELECT)

      { $this->_conn = Doctrine_Manager::getInstance()->getConnection('slave_' . rand(1, 4)); // All other queries are writes so they need to go to the master }

      else

      { $this->_conn = Doctrine_Manager::getInstance()->getConnection('master'); }

      }
      }

      However we are actually forcing all queries after the first access to the master to be run against the master (including selects). Note the example should probably be changed to use setConnection(). However even when using setConnection() it seems like changing the connection can cause issues when running a select on a model with a behavior (in our case we were using i18n). Therefore we believe there is some issue that is caused through the event system, because otherwise queries work just fine even when changing the connection as per the above described code.

      We managed to fix things, by not setting the connection explicitly and instead simply using setCurrentConnection('master'), so the bug does not affect us anymore. However this seems to indicate some issues deep inside the event-behavior-template code.

        Activity

        Hide
        Jordi Boggiano added a comment -

        In case the above post is confusing, note that doing $this->_conn = masterconn worked fine for the INSERT, it just broke when doing a subsequent SELECT of a translateable (I18n behavior) model and its Translation table with the following exception:

        Exception (Exception): Unknown relation alias Translation (#0)</h1>thrown in file /Library/WebServer/Documents/liip/infocube/ext/db-doctrine/lib/Doctrine/Relation/Parser.php at line 237
        backtrace:
        #1 Doctrine_Relation_Parser->getRelation called in file /Library/WebServer/Documents/liip/infocube/ext/db-doctrine/lib/Doctrine/Relation/Parser.php at line 235

        Show
        Jordi Boggiano added a comment - In case the above post is confusing, note that doing $this->_conn = masterconn worked fine for the INSERT, it just broke when doing a subsequent SELECT of a translateable (I18n behavior) model and its Translation table with the following exception: Exception (Exception): Unknown relation alias Translation (#0)</h1>thrown in file /Library/WebServer/Documents/liip/infocube/ext/db-doctrine/lib/Doctrine/Relation/Parser.php at line 237 backtrace: #1 Doctrine_Relation_Parser->getRelation called in file /Library/WebServer/Documents/liip/infocube/ext/db-doctrine/lib/Doctrine/Relation/Parser.php at line 235
        Hide
        Jonathan H. Wage added a comment -

        It is hard to understand the issue, can you provide a test case?

        Show
        Jonathan H. Wage added a comment - It is hard to understand the issue, can you provide a test case?
        Hide
        Lukas Kahwe added a comment -

        We already spend well over 2 hours together on project time to find a work around as noted above and I must admit now our motivation is not so big to dig deeper, especially since we didn't find the cause in this time and have the feeling its pretty impossible to fix without huge risks.

        Essentially I think all you need to do to reproduce the issue is use the cookbook code and issue some write query and afterwards do a select on a model that has the translatable behavior. It then gave us the above Exception.

        Our code worked slightly different since we did not use a random slave, instead we always used a local slave by default, but the first write and any queries thereafter would get send to the master. The code is public and the diff's show what we had to change to get things working. Note that the slave "localhost" connection was the default connection:
        http://fisheye.liip.ch/browse/PUB/okapi2/ext/db-doctrine/trunk/inc/DQ.php?r1=13118&r2=
        http://fisheye.liip.ch/browse/PUB/okapi2/ext/db-doctrine/trunk/inc/DR.php?r1=13118&r2=

        Show
        Lukas Kahwe added a comment - We already spend well over 2 hours together on project time to find a work around as noted above and I must admit now our motivation is not so big to dig deeper, especially since we didn't find the cause in this time and have the feeling its pretty impossible to fix without huge risks. Essentially I think all you need to do to reproduce the issue is use the cookbook code and issue some write query and afterwards do a select on a model that has the translatable behavior. It then gave us the above Exception. Our code worked slightly different since we did not use a random slave, instead we always used a local slave by default, but the first write and any queries thereafter would get send to the master. The code is public and the diff's show what we had to change to get things working. Note that the slave "localhost" connection was the default connection: http://fisheye.liip.ch/browse/PUB/okapi2/ext/db-doctrine/trunk/inc/DQ.php?r1=13118&r2= http://fisheye.liip.ch/browse/PUB/okapi2/ext/db-doctrine/trunk/inc/DR.php?r1=13118&r2=
        Hide
        Lukas Kahwe added a comment -

        we thought we had the issue fixed but ran into another issue today. we then noticed that the issue goes away if we just copy the $tables property from the old connection to the new connection. there is a getTables() method, but there is only a addTable() method, would be nice to have a addTables() method that is faster. or maybe a switchFrom() method that accepts the old connection and does whatever it needs to.

        And again it would be nice to update the cookbook entry.
        Here are our updated Doctrine_Query and Doctrine_Record classes:
        http://fisheye.liip.ch/browse/PUB/okapi2/ext/db-doctrine/trunk/inc/DQ.php
        http://fisheye.liip.ch/browse/PUB/okapi2/ext/db-doctrine/trunk/inc/DR.php

        Show
        Lukas Kahwe added a comment - we thought we had the issue fixed but ran into another issue today. we then noticed that the issue goes away if we just copy the $tables property from the old connection to the new connection. there is a getTables() method, but there is only a addTable() method, would be nice to have a addTables() method that is faster. or maybe a switchFrom() method that accepts the old connection and does whatever it needs to. And again it would be nice to update the cookbook entry. Here are our updated Doctrine_Query and Doctrine_Record classes: http://fisheye.liip.ch/browse/PUB/okapi2/ext/db-doctrine/trunk/inc/DQ.php http://fisheye.liip.ch/browse/PUB/okapi2/ext/db-doctrine/trunk/inc/DR.php
        Hide
        Jordi Boggiano added a comment -

        We just had another funny debugging session related to this. It turns out that the Table objects have a relation to the connection, and if you query a new model that wasn't initialized yet using ->from(), it works because it just gets the current connection passed. However, if you query a new model within a JOIN, then it apparently takes the connection from the related model you're joining from. In our case, the related model was already initialized but had an instance of the old (slave) connection, and so the new model was initialized using the wrong connection, and then the DQL parser exploded trying to resolve relations.

        Long story short, adding $table->setConnection($conn); to all tables while switching to the master connection resolved it. The code is updated and you can still view it at the above URLs, or straight in the SVN repo at http://svn.liip.ch/repos/public/okapi2/ext/db-doctrine/trunk/inc/DQ.php

        Show
        Jordi Boggiano added a comment - We just had another funny debugging session related to this. It turns out that the Table objects have a relation to the connection, and if you query a new model that wasn't initialized yet using ->from(), it works because it just gets the current connection passed. However, if you query a new model within a JOIN, then it apparently takes the connection from the related model you're joining from. In our case, the related model was already initialized but had an instance of the old (slave) connection, and so the new model was initialized using the wrong connection, and then the DQL parser exploded trying to resolve relations. Long story short, adding $table->setConnection($conn); to all tables while switching to the master connection resolved it. The code is updated and you can still view it at the above URLs, or straight in the SVN repo at http://svn.liip.ch/repos/public/okapi2/ext/db-doctrine/trunk/inc/DQ.php

          People

          • Assignee:
            Jonathan H. Wage
            Reporter:
            Lukas Kahwe
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated: